Linux进程 (冯诺依曼体结构 管理 PCB 进程状态 僵尸进程 孤儿进程 运行阻塞挂起状态 进程优先级)

avatar
作者
猴君
阅读量:0

文章目录

一.冯·诺依曼体系结构

在这里插入图片描述
在这里插入图片描述
那么问题就来了,为什么要加一个储存器
直接输入设备–>CPU–>输出设备不好吗?
在这里插入图片描述
短板在输入设备和输出设备,所以加了个存储器
在这里插入图片描述

在计算机里面,离CPU越近,效率越高,造价越贵
存储金字塔
在这里插入图片描述
总结:硬件流动角度,数据层面中:(蓝色箭头)
1.CPU不和外设直接打交道,CPU之和内存打交道
2.外设(输入和输出)的数据,不是直接给CPU的,而是先要放入内存中的

冯诺依曼结构能干什么?

在这里插入图片描述

引例:“你给你的朋友用QQ发送你好!!”的过程

在这里插入图片描述

二.操作系统

概念

开机的操作就是启动操作系统
操作系统是一款软硬件资源管理的软件(比如插个U盘,电脑会显示,可以往U盘里写东西)
操作系统广义的认识:操作系统内核+操作系统的外壳周边程序
狭义:只是操作系统的内核
在这里插入图片描述
windows也可以没有图形化界面的
在这里插入图片描述
安卓的操作系统属于两层
在这里插入图片描述

结构图(不完整)

体系结构的层状划分结构如下
因为操作系统需要硬件的数据,那么每次更新硬件,操作系统获得数据的方式可能跟上一个配对的硬件的方式不一样,那么操作系统就得跟着更新,才能与硬件配对,获取数据
所以操作系统不直接找硬件要相关数据,而是通过驱动层,这样只需要更新驱动就行。(驱动层是独立的,操作系统是核心,更新驱动层肯定比直接更新操作系统方便、安全)
在这里插入图片描述
就比如鼠标,在插入电脑的时候,不能直接使用,是因为驱动层还没有下好。右下角会弹窗显示插入或者鼠标亮了(现在插进去响一声),才能使用。

为什么要有操作系统?

举个例子:
学校有椅子、桌子、粉笔、图书馆里的书、体育器材
角色有老师、保安、校长、教导主任、医生
图书馆里的书需要图书馆管理员管理,椅子桌子坏了找谁报修,学生生病找谁
有了角色的担任,管理起来就会变得方便
操作系统就是对软硬件进行管理
为用户提供提供一个良好(稳定的、安全的、高效的)运行环境
良好的反例是指:用电脑玩原神,10分钟一黑屏,5分钟一重启,就是因为某个硬件造成的。

尝试理解操作系统

管理

管理在生活中无非在做两件事:1.决策 2.执行
比如说不想上今天的早8,这就决策。今天去早8了,这叫执行
在学校层面:校长为管理者,学生是被管理者
在这里插入图片描述

随着被管理的学生的增多,同学的信息也变得非常多,校长很难管理
但是校长会C语言,写了一个关于学生属性的表
在这里插入图片描述
张三的属性就可以用结构体表达出来
在这里插入图片描述
学生有很多人,校长要在5W个学生中找到张三同学,为了节省时间,校长就加了给指针,形成了链表
校长对学生的管理工作(日常),变成了对链表的增删查改(计算机语言)
在这里插入图片描述

于是校长完成了对计算机的建模工作,也就是对学生的管理工作
校长想开除张三,就变成了删除张三的节点
综上所述,管理学生:先把学生的信息描述起来,然后再组织
结论:任何管理:先描述,再组织
引例:C++先提供描述的能力,STL标准库,有各种容器,提供组织的能力
在这里插入图片描述
那么如何管理硬件呢?
比如插入鼠标的一瞬间,进程管理会创建一个关于鼠标的结构体,把鼠标的驱动程序读取到的数据写入该进程(先描述),并以算法(链表等)的形式插入前面的节点后面。(再组织)
在这里插入图片描述

不仅仅是进程管理是这样,只要是与管理相关的都大差不差

结构图(完整)

在这里插入图片描述
谈谈在操作系统上层的部分
作为用户能否直接访问底层硬件吗?
故事:
在这里插入图片描述

隔壁的校长是接触不到张三的,万一张三被拐走了,辅导员找不到人了就是管理人员的失职。要找也是找张三的校长
所以任何访问硬件的操作,都得通过操作系统来做
我们(用户)用C语言中的fopen fclose就经过文件管理,再写进磁盘,绕不过操作系统
同理printf是从显示器上读取数据,scanf是从键盘上读取数据,也是绕不开操作系统的
那用户能否直接访问操作系统呢?
故事:
在这里插入图片描述

在这里插入图片描述
又比如:现在的你改一改操作系统,然后打起了原神,就因为改了操作系统直接蹦掉了。所以用户是不能直接接触操作系统的
上面的故事映射到计算机里面就是:银行中的柜台就是系统调用接口
这样就可以受管控的使用操作系统
在这里插入图片描述
故事进入第二阶段:
作为新时代的青年,准备材料去存钱开户什么的都知道。
但是有一天,来了一个老奶奶要存1000万,但是不会操作
在这里插入图片描述
银行经理就是外壳程序,帮助用户开发等操作
在这里插入图片描述
开发的时候,直接使用系统调用接口,是不具有跨平台性的,在Linux上能跑,windows可不一定能跑
例子:
在这里插入图片描述

总结:

在这里插入图片描述

三.进程

操作系统中,进程可以同时存在非常多
在这里插入图片描述
如何管理这么多进程呢?
先描述,再组织

进程是什么?

假设我们要运行一个名为a.out的可执行文件(程序 = 代码 + 数据)
根据冯诺依曼结构,任何可执行程序都需要进入内存,交给CPU处理
问题来了,下面图中的内存是进程吗?
在这里插入图片描述
可以这样想:如果文件很多,哪个先运行,哪个后运行,什么时候到我运行,堆和栈在哪?
所以:
在这里插入图片描述
操作系统想要管理进程:就得先描述,再组织。
在这里插入图片描述

PCB

PCB全称process control block
PCB在哪里?
在操作系统里,我们电脑或手机开机就是加载操作系统(操作系统也是软件)
在这里插入图片描述
注意的是:操作系统是对PCB的管理,而非对可执行程序管理

为什么要有PCB?

OS要进行管理,就得先描述,在组织

Linux中的PCB

在这里插入图片描述
通常进程排队指的是PCB(struct task_struct)排队,而不是数据
在这里插入图片描述
因为队列的首部的节点是a.out
所以CPU会把a.out的数据弄到CPU中去运行
在这里插入图片描述
总结:调度运行进程,本质就是让进程控制task_struct进行排队
举个通俗点的例子:
同学投简历,大厂会筛选简历,就是对简历(进程)的增删查改,就是对同学(数据)的管理
所以在Linux中进程的概念:进程 = 内核task_struct 结构体 + 程序的代码和数据

进程的task_struct本身内部的属性有哪些?

例子:
Makefile文件

myprocess:myprocess.c 	gcc -o $@ $^ .PHONY:clean clean: 	rm -f myprocess 

myprocess.c文件

#include <stdio.h> #include <unistd.h>                                                        int main() {     while(1)     {         printf("I am a process!\n");         sleep(1);     }     return 0; }          

在这里插入图片描述
如何查看当前的进程呢?
ps axj
ps:查看当前的进程
a:是all的意思
xj:是显示进程的详细信息
axj的顺序可以乱
一个可执行文件和其进程的名字默认是一样的
查看myprocess文件的进程的命令:

ps axj | grep myprocess 

会发现有两个关于myprocess的进程,是因为grep本身的进程也被查到了
在这里插入图片描述
显示的每一个信息是什么呢?
显示进程的第一行

ps axj | head -1 

在这里插入图片描述
结合起来:
在这里插入图片描述

一个进程,如何知道自己的pid?
前面讲了,用户无法直接访问操作系统
在这里插入图片描述

就需要系统调用接口getpid
在这里插入图片描述
在这里插入图片描述
myprocess.c的代码

#include <stdio.h> #include <unistd.h> #include <sys/types.h>                                                        int main() {     pid_t id = getpid();     while(1)     {         printf("I am a process!,pid:%d\n",id);         sleep(1);     }     return 0; }            

发现进程中的pid与运行起来的pid一样
在这里插入图片描述

在这里插入图片描述

终止进程

ctrl + C 就是在用户层面终止进程

kill -9 pid可以直接杀掉进程

进程创建的代码方式(fork函数)—重操作,轻原理

发现还有一个getppid,第一个p是parent,第二个p是process,意思是获得当前进程的父进程的id
在这里插入图片描述
看一下父进程id是什么
myprocess.c的代码:

#include <stdio.h> #include <unistd.h> #include <sys/types.h>                                                        int main() {     pid_t id = getpid();     pid_t parent = getppid();     while(1)     {         printf("I am a process!,pid:%d,ppid:%d\n",id,parent);         sleep(1);     }     return 0; }            

跑起来会发现
在这里插入图片描述
其中18839是什么?
是bash
bash是父进程,是命令行解释器,在Linux权限篇中讲了bash是媒婆,派实习生(子进程)的的故事
在这里插入图片描述
创造子进程,因为用户是不能直接去触碰操作系统的,所以用系统调用接口fork。
在这里插入图片描述
myprocess.c的代码如下

#include <stdio.h> #include <unistd.h> #include <sys/types.h>  int main() { 	printf("process is running,only me!\n"); 	sleep(3); 	fork();                                                                                      	printf("hello world\n"); 	sleep(5); 	return 0; } 

运行上面的可执行程序时,运行下面的指令,方便观察进程。-v 是去掉grep的进程

while :; do ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep;sleep 1;done 

运行结果:
在这里插入图片描述
可以发现
在这里插入图片描述

我们为什么要创建子进程?

想让子进程和父进程执行不一样的代码
fork会返回两个值
在这里插入图片描述
成功后,子进程的 PID 将在父进程中返回,在子进程中返回 0。 失败时,父进程中返回 -1,不创建子进程。
验证一下fork
process的代码如下:

#include <stdio.h> #include <unistd.h> #include <sys/types.h>                                                     int main() {     printf("process is running,only me!\n");     sleep(3);     pid_t id = fork();     if(id == -1)  //失败     {         return 0;     }     else if(id == 0)  //子进程     {         while(1)         {         	printf("id:%d,I am child process,pid:%d,ppid:%d\n",id,getpid(),getppid());             sleep(1);         }     }     else  //父进程     {         while(1)         {                 printf("id:%d,I am parent process,pid:%d,ppid:%d\n",id,getpid(),getppid());             	sleep(2);         }     }     return 0; } 

会发现确实有两个返回值,并且子进程的pid将在父进程中返回
在这里插入图片描述
在这里插入图片描述
于是就出现了两个问题:
1.同一个id,怎么可能即是 == 0,又是 > 0?
2.fork为什么会有两个返回值,并且返回两次
父进程的代码从磁盘中带出来的,子进程只能copy父进程给的代码。
数据上有些独特
在这里插入图片描述

解答一下第二个问题
在这里插入图片描述

多进程

代码如下:

#include <stdio.h> #include <unistd.h> #include <sys/types.h>  void RunChild() {     while(1)     {         sleep(1);         printf("I am child process,pid:%d,ppid:%d\n",getpid(),getppid());     } }  int main() {     int i = 0;     const int num = 5;  //创建5个子进程     for(i = 0;i<num;i++)     {         pid_t id = fork();         if(id == 0)  //子进程进入         {             RunChild();         }         sleep(1);  //父进程继续往下走     }      while(1)     {         sleep(1);         printf("I am parent process,pid:%d,ppid:%d\n",getpid(),getppid());     }     return 0; }  

可以看到进程逐渐变多
在这里插入图片描述

task_struct的内容

标识符:ppid pid 用来和别的进程做区分
状态:任务状态、退出代码、退出信号等
优先级:想对于其它进程的优先级
程序计数器: 程序中即将被执行的下一条指令的地址
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
其他信息

查看进程(通过/proc查找)

进程的信息也可以通过 /proc 系统文件夹查看
在这里插入图片描述
假设要获取进程的PID==1的程序
直接查看/proc/1文件就行
举个例子:
在这里插入图片描述
进入proc文件,会发现文件里面的目录都是进程,目录名称就是PID
在这里插入图片描述
其中,/proc/PID目录中值得注意的是这两个
第一个表示的是:进程的当前工作路径
第二个表示的是:进程的PCB中会记录自己对应的可执行程序的路径
在这里插入图片描述
把这个进程干掉,发现程序还在跑。(这个图片显示不出来,得自己实验)
因为把磁盘中的文件删掉了,但是进程的代码与数据已经在内存里了
在这里插入图片描述
然后发现cwd和exe没了
在这里插入图片描述
每个进程在启动的时候,会记录自己当前在哪个路径下启动
验证:下面是个简单的文件函数

#include <stdio.h>   int main() {     FILE* fp = fopen("log.txt","w");     (void)fp;//ignore warning     return 0; } 

因为是在该目录下运行的进程(a.out),所以默认在该目录下创建log.txt文件
在这里插入图片描述
更改进程的所在路径
用到的函数时chdir
在这里插入图片描述

#include <stdio.h>  #include <unistd.h> #include <sys/types.h>  int main() {     chdir("/home/sjl");//更改的路径     FILE* fp = fopen("log.txt","w");     (void)fp;//ignore waring     fclose(fp);     while(1)//显示出进程在运行     {         printf("I am a process,pid:%d\n",getpid());         sleep(1);     }     return 0; } 

进程的路径被更改
在这里插入图片描述
会发现在更改的路径下创建log.txt,而运行可执行程序的路径下时没有的
在这里插入图片描述
所以一旦把当前进程的工作目录改了,那么新建对应的一个文件,他就在改过进程的当前目录下

四.进程状态

大概就是下面这种形式
在这里插入图片描述
下面的状态在kernel源代码里定义:

static const char * const task_state_array[] = { "R (running)", /* 0 */ "S (sleeping)", /* 1 */ "D (disk sleep)", /* 2 */ "T (stopped)", /* 4 */ "t (tracing stop)", /* 8 */ "X (dead)", /* 16 */ "Z (zombie)", /* 32 */ }; 

R状态 S状态

引例:

#include <stdio.h> #include <sys/types.h> #include <unistd.h>  int main() {     while(1)     {         printf("I am a process,pid:%d\n",getpid());     }     return 0; } 

运行的时候老样子,用以下指令查看进程(可执行程序为a.out)

while :; do ps ajx | head -1 && ps ajx | grep a.out | grep -v grep;sleep 1;done 

会发现是S+的状态,是sleep,休眠状态
在这里插入图片描述
然后把printf注释掉

#include <stdio.h> #include <sys/types.h> #include <unistd.h>  int main() {     while(1)     {         //printf("I am a process,pid:%d\n",getpid());     }     return 0; } 

再次运行代码,会发现是R+状态,R为进程运行状态
在这里插入图片描述
原因:打印的时候,是往屏幕上打印的,屏幕是外设,CPU运行比外设快很多,CPU需要等显示屏的资源就绪。所以CPU大部分处于S状态,运气好的时候遇到CPU正在执行printf就能查到在R状态
S(休眠状态)本质分为两种:
第一种:进程在等待“资源”就绪(就是上面的例子)
第二种:可中断睡眠(进程处于睡眠的状态(比如sleep函数),但依旧可以被ctrl + c中断)

状态+中的+是什么意思?

代表的是在前台运行还是后台运行
在进程后面加个&代表在后台运行
在这里插入图片描述
运行后你就会发现ctrl + c中止不了
用kill -9 PID终止进程
在这里插入图片描述

T状态 t状态

显示出Linux的信号的指令:-l是list

kill -l 

其中9号信号是不是很眼熟,杀掉进程
在这里插入图片描述
上面的信号底层就是宏,跟C语言中的INT_MAX意义差不多
其中19号信号SIGSTOP就是暂停进程
验证:

#include <stdio.h> #include <sys/types.h> #include <unistd.h>  int main() {     while(1)     {         sleep(1);         printf("I am a process,pid:%d\n",getpid());     }     return 0; } 

S状态直接变为T状态
在这里插入图片描述
T状态:让进程暂停,等待被进一步唤醒(进程被暂停了,自动变为后台)
18号信号SIGCONT,continue的意思,让进程继续
在这里插入图片描述
调试就是进程暂停
遇到断点处,进程就暂停了
在这里插入图片描述

D 状态

D:Linux系统比较特有的一种状态(disk是磁盘)
因为配置的原因很难演示出来,所以拿图来讲解:
进程要往磁盘中存1个GB的数据
在这里插入图片描述
内存严重不足,操作系统马上被毙掉了,然后看见这个进程悠然自得的SLEEP,一怒之下,把他删了。磁盘找不到了,造成了数据的丢失
在这里插入图片描述
这不行啊,好比说内存是银行的系统,被删掉的进程是银行的转账记录,直接被干没了,造成了上百万的损失。
为了防止这类事情的发生,规定凡是进程要进行数据IO等待外设的时候,进程要将自己的状态设成D状态
D状态:不可被杀,被称为深度睡眠,也被称为不可中断睡眠(S就是浅度睡眠,可被杀和中断)
要唤醒D状态有两种方法:
1.进程自己醒来
2.重启,重启不行就断电

Z 状态(僵尸进程) 与X 状态

一个进程退出的时候,他会把自己退出的信息保留在PCB当中,如果没有人读取PCB中退出进程的消息,这个进程就一直不释放,一般会把代码和数据释放掉,但PCB内容与数据结构会一直存在,直到将来对该进程进行等待,如果不等待就一直处于僵尸状态。如果等待了就会转化为X状态,进而将进程所有的资源全部释放掉
引例:

#include <stdio.h> #include <sys/types.h> #include <unistd.h>  int main() {     pid_t id = fork();     if(id == 0)     {         //child         int cnt = 5;         while(cnt)//子进程运行5次后退出         {             printf("I am child,cnt:%d,pid:%d\n",cnt,getpid());             sleep(1);             cnt--;         }     }     else      {         //parent         while(1)//父进程一直不退出         {             printf("I am a parent,running always!pid:%d\n",getpid());             sleep(1);         }     }     return 0; } 

子进程运行结束后就是Z状态(僵尸状态)

在这里插入图片描述
子进程运行完毕,但需要维持自己的退出信息,在自己的进程task_struct会记录自己的退出信息,未来让父进程来读取
在这里插入图片描述
因为X状态释放是一瞬间的,所以查不出来
平时子进程创建出来是要完成任务的,得知道完成任务怎么样(获取子进程退出的信息)
kill不掉僵尸进程的,已经死进程了,杀不了了。

孤儿进程

如果父进程先退出了,那么子进程就是孤儿进程
就是与僵尸进程相反,所以验证的代码也相反:

#include <stdio.h> #include <sys/types.h> #include <unistd.h>  int main() {     pid_t id = fork();     if(id == 0)     {         //child         while(1)         {             printf("I am child,pid:%d\n",getpid());             sleep(1);         }     }     else      {         int cnt = 5;         //parent         while(cnt)         {             printf("I am a parent,cnt:%d,pid:%d\n",cnt,getpid());             sleep(1);             cnt--;         }     }     return 0; } 

发现两个S的进程就剩1个S的进程,剩下的那个S进程就是孤儿进程
在这里插入图片描述
问题就来了:父进程都没了,谁去回收孤儿进程?
答:孤儿进程一般都会被1号进程(OS本身)进行领养的
孤儿进程为什么要被OS领养?
答:依旧要保证子进程正常被回收
孤儿进程是可以被kill的
以前我们启动的所有进程(运行C语言代码)。怎么从来没有关心国】过僵尸进程呢?内存泄漏?
答:直接在命令行中启动的进程,他的父进程是bash,bash会自动回收新进程的Z
父进程的一般核心工作都是回收子进程

纯理论:进程的阻塞和挂起,运行

大多数书上的进程状态
在这里插入图片描述

运行状态

在这里插入图片描述
进程在运行队列中,该进程的状态就是R状态。
R状态不是指直接在CPU上去运行,而是值我已经准备好了,可以随时被调度了
一个进程一旦持有CPU,会一直运行到这个进程结束吗?
不会,就比如里面写个死循环,CPU调度就不会走了,其他进程被卡死了。
现实就是打着原神,微信还能收到信息。
是因为当代的内核基于时间片轮转调度的。
假设时间片设置的2毫秒,2毫秒一到,当前进程就会在CPU上剥离下来,插到队列的尾部,然后下一个进程上前,进入CPU
在这里插入图片描述
这样就可以让多个进程以切换的方式进行调度,在一个时间段内同时得以推进代码。就叫做并发
Linux不是这样调度的,上面方法太简单了。只是调度算法的一种。
如果存在两个CPU,就有两个调度队列
在这里插入图片描述
根据不同的进程,放到不同队列,也可以放进两个队列
任何时刻,都同时有多个进程在同时运行,我们叫做并行

阻塞状态

问题:我们在写C语言的时候,用过一个接口scanf,如果我们不输入的话,进程处于什么状态?另外scanf在等待什么资源呢?
测试代码如下:

#include <stdio.h>  int main() {     int a = 0;     scanf("%d",&a);     printf("a = %d\n",a);     return 0; } 

会发现是S状态,其实D也算阻塞状态,不过无法演示
在这里插入图片描述
他在等什么呢?在等键盘资源是否就绪,键盘上面有没有被用户按下的按键,按键数据交给进程
键盘上面没数据,进程是不OK,该进程并没有被运行的(R状态),所以一定不在运行队列中
操作系统要对所有的硬件做管理,那么操作系统如何对硬件做管理?
管理肯定离不开先描述,在组织
在这里插入图片描述
一个进程如何等待一个设备呢?
不只是CPU才有等待队列,设备中也有等待队列wait_queue
在这里插入图片描述
演示一下scanf等待键盘资源的总过程:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:阻塞和运行状态的变化,往往伴随着PCB被连入到不同的队列中
入队列的不是进程的代码和数据,而是进程的task_struct

挂起状态

我们在装系统的时候,会有一个swap分区,大多数情况swap分区是内存的1.5倍2倍,可以自己定义。
当OS中内存吃紧,且有进程处于阻塞状态(暂时不会被调度),那么就把该进程的代码和数据唤出到swap分区中。这样内存就会腾出空间
这种状态叫做阻塞挂起态

在这里插入图片描述

如果该设备又等待就绪了,就会把进程的代码和数据唤入到内存
在这里插入图片描述
这样可以更合理的使用内存资源
还有很多挂起,就绪挂起等。本质都是一样的。
频繁的唤入唤出会导致效率问题。牺牲效率换取空间
不建议把swap分区放大太,因为操作系统会过渡依赖swap分区,一压力大就唤出。要逼着操作系统合理的分配内存
swap分区的位置

ls /proc/swaps 

进程切换

CPU内部的所有寄存器中的临时数据,叫做进程的上下文
在这里插入图片描述
寄存器本身是硬件,具有数据的存储能力,CPU的寄存器硬件只有一套
但CPU内部的数据可以有多套,有几个进程,就有几套和该进程对应的上下文数据

进程优先级

什么是优先级?

指定进程获取某种资源(比如CPU)的先后顺序
进程控制模块task_struct中的内部字段有一个或多个整型(比如int prio =)的优先级数字
Linux中优先级数字越小,优先级越高

为什么要有优先级?

进程访问的资源(CPU)是有限的
进程比硬件资源多,显示屏就一个,网页有很多
操作系统关于调度和优先级的原则:分时操作系统,保证了基本公平
如果进程因长时间不被调度,就造成了饥饿问题(比如学生打饭,教导主任差一下队,校长插一下队)

如何查看优先级呢?

引例:

#include <stdio.h> #include <unistd.h>  int main() { 	while(1)     {     	printf("I am a process,pid:%d\n",getpid());     	sleep(1);     }     return 0; } 

查看当前终端的进程

ps -l 

想查看全部终端的进程

ps -al 

PRI:进程优先级
NI:进程优先级的修正数据(nice值),新的优先级 = 优先级 + nice
在这里插入图片描述

top更改进程优先级

top 

先输入top
在这里插入图片描述
然后输入r
在这里插入图片描述
输入需要调整优先级的PID
在这里插入图片描述
输入100,然后按回车
在这里插入图片描述
会发现优先级是99,不是80+100
在这里插入图片描述
这是因为nice并不能任意调整,是有范围的(-20~19)
如果能随便调,把优先级调很高,就可能会一直运行一个进程,影响了调度的平衡
第二次改的时候不让改了,因为一个进程的优先级是不能频繁改的
在这里插入图片描述
这里切root用户更改,nice的值为6
在这里插入图片描述
发现不是99+6,而是80+6
因为每次调整优先级,都是从80开始的
在这里插入图片描述

nice与renice

这两也可以更改优先级
nice命令格式:nice -n [NI值] [命令]加不加n都行
在这里插入图片描述
renice命令格式:renice [NI值] [PID]
在这里插入图片描述

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!