在我们的计算机层次结构中,操作系统是处于一个承上启下的层次。如下图~
在计算机中,操作系统的定位是一个管理者,对上管理在系统中运行的进程,对下通过驱动程序管理各种硬件。
说到进程,首先得稍微解释一下,什么叫做程序。
程序:程序是以某种语言编写,为完成某个特定任务的一系列指令和数据的有序集被称之为程序。
那么什么是进程?
从用户的角度来解读,进程就是程序的一次动态的执行过程。
但是想要深入理解进程的概念,一定要知道操作系统是怎么解读进程的。
首先要了解进程控制块(Process Control Block),简称PCB。进程属性的集合全部被放在PCB之中,在Linux下,PCB是一个叫做task_struct的结构体之中。
学过C数据结构的同学应该都知道,结构体用来描述一个结构的信息,通过指针我们把这些结构组织起来,形成不同的数据结构。比如链表,二叉树,堆等等。
而操作系统也是通过这样的方式对我们的PCB来进行管理的。
那么操作系统通过PCB来对进程进行管理,那么PCB中大概有什么关键信息呢?
进程标识符,进程状态,进程优先级,程序入口地址,各种计时信息,文件系统的相关信息,现场保护信息等等一系列的信息。
在Linux下,进程标识符就是pid,这个可以通过命令来获取,也可以通过一些系统调用接口来获取,如ps命令,getpid()接口。pid是在操作系统下唯一标识一个进程存在的标识符,用于区别其他进程,同样的道理,一个PCB也只唯一标识一个进程。
在Linux下,一个进程可以有七种不同的状态。
R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行要么是在运行队列里。
S睡眠状态(sleeping):意味着进程在等待事件完成(可中断睡眠)。
D磁盘休眠状态(Disk sleep):也叫不可中断睡眠状态,在这个状态进程通常会等待IO的结束。
T停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止(T)进程。这个暂停的进程可以通过发送SIGCONT信号让进程继续运行(关于信号后面还会继续更新到相关内容)。
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
还有t(tracing stop)跟踪状态和Z(zombie)僵尸状态。
僵尸状态是进程已经终止,但是还占用这系统中的资源没有释放,这种状态对系统是有害的。
僵尸进程这种状态比较特殊。当进程退出并且父进程没有读取到子进程退出的返回代码就会产生僵尸进程。
所以,只要子进程推迟,父进程还在运行,但父进程没有读取子进程的状态,子进程进入Z状态。
用这段小程序在Linux系统下运行,然后用查看进程状态的命令查看就可以看到进程变成了Z状态。
#include
#include
#include
int main()
{
pid_t id = fork();
if(id == -1){
perror("fork");
return 1;
}
else if(id == 0){
printf("child pid: %d\n",getpid());
sleep(3);
exit(0);
}else{
printf("parents pid:%d\n",getpid());
sleep(30);
exit(EXIT_SUCCESS);
}
return 0;
}
孤儿进程:父进程先退出,子进程就被称为孤儿进程。父进程如果提前退出,那么子进程后退出,进入Z之后,该怎么办呢?这个时候会产生对系统资源的浪费的僵尸进程。操作系统当然不会眼睁睁的看着这种事情发生,所以当系统中产生孤儿进程,就会被1号init进程领养,当然会被init进程回收,这里的init进程可以先理解为操作系统的进程。