目录
看Linux源码中的说法
如何查看进程状态?
各个状态的关系
僵尸进程
举个栗子
现象
僵尸进程的危害
孤儿进程
举个栗子
现象
进程的优先级
基本概念
为什么要有进程优先级?
查看系统进程
进程的大致属性
进程优先级vs进程的权限
Linux进程的优先级范围
查看进程优先级的命令
有关进程的其他概念
看Linux源码中的说法
-
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
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运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
-
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
-
D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
-
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
-
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
如何查看进程状态?
各个状态的关系
-
使用下面的命令
ps aux|ps axj
-
我们让一个test程序一直执行,然后通过上面的命令进行查看,可以看见此时进程的状态是R+
僵尸进程
-
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
-
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
-
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
举个栗子
-
我们人为地创建一个僵尸进程
#include <stdio.h>
#include <stdlib.h>
int main()
{pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id > 0){ //parentprintf("parent[%d] is sleeping...\n", getpid());sleep(30);}else{printf("child[%d] is begin Z...\n", getpid());sleep(5);exit(EXIT_SUCCESS);}return 0;
}
现象
我们使用自动监视脚本来监视进程的状态,随后启动上面的程序,可以发现过来一会有一个进程变成Z状态了
while :; do ps aux |grep test; sleep 1; echo "==================";done
僵尸进程的危害
-
进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
-
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!
-
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
-
内存泄漏?是的!
-
如何避免?后面会讲
孤儿进程
-
父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
-
父进程先退出,子进程就称之为“孤儿进程”
-
孤儿进程被1号init进程领养,当然要有init进程回收喽。
举个栗子
-
同样的,我们人为制造出孤儿进程的情况
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{pid_t id = fork();if(id < 0){perror("fork");return 1;}else if(id == 0){//childprintf("I am child, pid : %d\n", getpid());sleep(10);}else{//parentprintf("I am parent, pid: %d\n", getpid());sleep(3);exit(0);}return 0;
}
现象
-
同样使用监视脚本来监视进程状态,然后运行上面的程序,可以发现子进程在父进程退出后并没有立即退出,而是继续运行,且此时子进程的ppid从原父进程的ppid变成了1,这其实是bash的pid,这就是被“领养了”
进程的优先级
基本概念
-
cpu资源分配的先后顺序,就是指进程的优先权(priority)。
-
优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
-
还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能
为什么要有进程优先级?
-
因为操作系统的资源是有限的,所以必须将进程分为三六九等,保证很重要的进程能够优先获得资源
查看系统进程
-
使用下面的命令
ps -l
进程的大致属性
-
UID : 代表执行者的身份
-
PID : 代表这个进程的代号
-
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
-
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
-
NI :代表这个进程的nice值
进程优先级vs进程的权限
-
进程的优先级保证进程的到资源,只不过得到资源的时间不同
-
进程的权限是决定进程能还是不能的到某种资源
Linux进程的优先级范围
-
Linux采用两种不同的优先级范围,一种是nice值,另一种是实时优先级。
-
nice值:nice值得范围是-20~19,默认值是0。越大的nice值意味着更低的优先级,也就是说nice值为-20的优先级最高。
-
实时优先级:实时优先级的范围是0~99,其值得意义与nice值相反。即:越高的实时优先级数值意味着进程优先级越高。Linux的进程可分为普通进程和实时进程,实时进程都是一些对响应时间要求比较高的进程,因此实时进程的优先级比普通进程的优先级要高。
-
Linux中进程默认的实时优先级为80
-
Linux支持动态优先级调整
-
pri(新) = pri(旧)+nice
-
用户创建的进程的优先级范围一般是60~99,因为操作系统自己也会启动一些进程,要保证这些进程的优先级高于用户创建的进程的优先级
查看进程优先级的命令
-
top
-
进入top后按“r”–>输入进程PID–>输入nice值
有关进程的其他概念
-
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
-
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
-
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
-
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发