这篇文章,我会就我的理解对PCB和进程调度做出我的看法。
首先,进程,什么是进程?
课本上的概念说,进进程是程序的一个执行实例,是一个正在执行中的程序。
从内核的角度来说,进程是担当分配系统资源的实体。
进程的信息被放在一个叫做进程控制块(PCB)的结构体中。这个结构体可以理解为进程属性的集合。linux称呼这个结构体叫做:task_struct。
task_struct是Linux内核的一种数据结构。被装载到内存里并且包含着进程的信息。
task_struct内容分类:
标识符:表述进程的唯一标识符,用来区别其他程序。
状态:进程状态有R(执行),S(睡眠),D(休眠),T(停止),X(死亡)等。
睡眠:进程在等待某事件完成。
休眠:也叫做不可中断睡眠。这个状态的进程通常会等待I/O的结束。
优先级:相对于其他程序的优先级。
程序计数器:程序中即将被执行的下一条指令的地址。
内存地址:包括程序代码和进程相关数据的指针。
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
进程调度:
在介绍进程调度之前,我想先介绍进程优先级。
进程的优先级是CPU分配系统资源的先后顺序。优先级高的进程有优先执行的权利。进程优先级可以改善系统性能。
调度策略和调度优先级是有内核确定的,进程可以通过调整nice值选择以更低优先级运行(通过调整nice值降低它对CPU的占用)。只有特权进程允许提高进程调度权限。
nice值越小,优先级越高。
进程可以通过nice函数获取或更改它的nice值。使用这个函数,进程只能影响自己的nice值,而不能影响其他进程的nice值。
#include
int nice(int incr);
返回值:成功返回新的nice值,出错返回-1.
incr参数被增加到调用进程的nice值上。如果incr太大,系统直接把它降到最大合法值,不给出提示。如果incr值太小,系统就给它提高到最小合法值。
getpriority函数可以向nice函数一样获取进程的nice值,但是它还可以获得一组相关进程的nice值。
#include
int getpriority(int which,id_t who);
若成功返回nice值,失败返回-1
其中参数which可以取三个值之一:PRIO_PROCESS表示进程,PRIO_PGRP表示进程组,PRIO_USER表示用户ID。which参数控制who参数是如何解释的。who参数选择感兴趣的一个或多个进程。如果who参数为0,表示调用进程、进程组或用户。
僵尸进程:
当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。
僵尸进程会以终止状态保存在进程表中,并且会一直等待父进程读取其退出状态。
所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程就进入僵尸状态。
下面是一个创建维持30s的僵尸进程例子。
#include
#include
int main()
{
pid_t id = fork();
if(id<0){
perror("fork");
return 1;
}
else if(id>0){
printf("parent[%d] is sleeping...\n",getpid());
sleep(30);
}else{
printf("child[%d] is begin Z...\n",getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}
孤儿进程
父进程先退出,子进程就被称“孤儿进程”。
孤儿进程被1好init进程收养,之后也有init进行资源回收。
一个init的子进程有可能是它直接产生的进程,也有可能是它收养的进程。
#include
#include
#include
int main()
{
pid_t id = fork();
if(id<0){
perror("fork");
return 1;
}
else if(id == 0){
printf("i am child,pid:%d\n",getpid());
sleep(10);
}else{
printf("i am parent,pid:%d\n",getpid());
sleep(3);
exit(0);
}
return 0;
}