目录
- 引言
- 僵尸进程
- 僵尸进程的状态
- 僵尸进程周边知识
- 孤儿进程
- 孤儿进程的状态
- 进程中的其他状态
- ①.R---表示进程运行状态。
- ②.S---表示进程的休眠状态。(进程什么都没做)
- ③T 和 t
- 进程的运行、阻塞和挂起
- 运行
- 阻塞
- 挂起状态:
引言
今天我们来将僵尸进程和孤儿进程以及其他的周边知识:进程的状态和进程的运行,阻塞和挂起。
僵尸进程
上个博客我们提到了进程,并且细致了说了什么事进程,所以我们今天就不在赘述了。那么什么又是僵尸进程呢?
定义:僵尸进程指进程已经退出,但资源并没有完全被释放。
可能还是很懵,那么我们就用代码演示。
代码分析:
我们要捏造一个代码已经退出了,但是资源没有释放的场景,那么我们就可以用fork()来创建子进程,并且让子进程先退出,查看它的状态。
#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
pid_t id=fork();
if(id<0) return -1;//小于0表示创建子进程失败
if(id==0)
{
//创建子进程成功
int cnt=5;
while(cnt--)
{
printf("我是一个子进程,我的pid是%d,ppid%d\n",getpid(),g etppid());
sleep(1);
}
}else{
//父进程
while(1)
{
printf("我是一个父进程,我的pid是%d,ppid%d\n",getpid( ),getppid());
sleep(1);
}
}
}
僵尸进程的状态
如下图,会发现子进程和父进程同时推进,但是在cnt为0的时候,子进程已经结束,但是父进程是死循环,并不会退出,会发现子进程STAT的状态变成了Z+。
Z:表示僵尸进程状态,+号表示在前台运行。
僵尸进程周边知识
子程序已经运行完毕,但是还需要维持自己的退出信息,在自己的进程task_struct会记录自己退出信息,未来让父进程来读取。如果没有父进程读取,僵尸进程会一直在。如果一直没有回收,就会引起内存泄漏问题。 僵尸进程不能被杀死,因为僵尸进程已经死了,无法杀死。
孤儿进程
孤儿进程我们从他的名字也能看得出来,是父进程先退出,但是子进程没有退出导致的。
定义:它的父进程已经终止(退出),但该进程本身仍在运行。当父进程提前结束时,操作系统内核会自动将孤儿进程的父进程重新设置为init进程(在Unix/Linux系统中,init进程通常是PID为1的进程,现代系统中可能是systemd)。
孤儿进程没有父亲会被init进程领养。
孤儿进程的状态
以下代码,会让父进程先退出。从运行截图,我们发现一开始子进程和父进程都是S+,但是当父进程退出的时候,子进程变成了S。这个时候就表示子进程变成了孤儿进程且已经被领养。孤儿进程会被转到后台运行。
#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
pid_t id=fork();
if(id<0) return -1;//小于0表示创建子进程失败
if(id==0)
{
//创建子进程成功
int cnt=10;
while(cnt--)
{
printf("我是一个子进程,我的pid是%d,ppid%d\n",getpid(),g etppid());
sleep(1);
}
}else{
//父进程
int cnt=5;
while(cnt--)
{
printf("我是一个父进程,我的pid是%d,ppid%d\n",getpid( ),getppid());
sleep(1);
}
}
}
问题: 为什么孤儿进程要被领养?
答:因为保证子进程正常被回收。
进程中的其他状态
状态的种类:
①.R—表示进程运行状态。
如图他是运行状态,但是大部分当输出一段话的时候会发现是S+,这是为什么呢?原因是我们的CPU太快了,Linux的原则是一切皆文件,显示器也不例外,他也是一个文件,当你的代码将内容显示到屏幕上,CPU一下子就解决了,但是从磁盘到内存到CPU很慢,所以你的CPU一直在等待。
②.S—表示进程的休眠状态。(进程什么都没做)
所谓的休眠状态就是进程太等待,可能是因为cpu太快了。 本质:进程在等待 “资源” 就绪。 且S是可中断睡眠。(ctrl+c)
③T 和 t
T ---让进程暂停,等待被进一步唤醒。 kill -19(暂停)/-18(继续) /-9(杀死进程)
t ---进程被追踪暂停。(调试情况,遇到断点就暂停)
④. ./可执行文件 +& —>表示在前台运行。没有+表示在前台。
⑤.x—死亡状态。
⑥.D— 深度睡眠/不可中断睡眠。 D的存在主要是保护重要进程不被干掉。如果非要中断有两种情况:断点重启和等待进程结束。
进程的运行、阻塞和挂起
这张图大家看着都很熟悉,很多教材都有,但是我们这里说的并不全面,只会说运行、阻塞和挂起。
运行
(1).进程运行时一定是在cpu上运行。每一个cpu都需要维护一个运行队列(数据结构)。
(2).进程在运行队列中,该进程的状态就是R状态(运行状态)。
(3).进程是基于时间片进程轮转调度的。让多个进程以切换的方式进行调度,在一个时间段内同时得以推进代码,这就叫做并发。
阻塞
问题:我们C语言中的scanf在等待你输入是属于什么状态呢?暂停吗?
答:是阻塞状态,S属于阻塞状态。等待某资源是都就绪。
(1).不止有CPU才有运行队列,各个设备也有自己的等待队列。
(2).阻塞指一个进程从进程队列里剥离下来,列到其他设备的队列里。
(3).当阻塞结束,把进程从其他设备的队列,在列会进程队列中交唤醒。
挂起状态:
(1).挂起就是将操作系统的暂时不用的进程,交换到磁盘中swap区。你在需要调度的时候,在换出。
(2).频繁地换入换出会导致效率问题。