Linux理解fork()和进程状态详解

文章目录

    • fork()
      • 理解fork
    • 进程状态
      • 操作系统下描述的状态
      • 具体的操作系统Linux下的进程状态
      • 运行状态就一定在运行吗?
      • S和D的区别
      • T状态
      • Z状态
      • 什么样的进程杀不掉
      • 孤儿进程 领养人:1
      • 操作系统的状态和Linux的状态对应图
  • 末尾

fork()

fork()

fork是什么?

C语言里的一个创建子进程的函数

作用:创建子进程

创建后有两个进程,一个父亲,一个儿子

父子共享用户代码 而用户数据各自私有一份

共享代码私有数据的目的:维护进程的独立性

创建子进程:子进程的创建是以父进程为模板的,即默认使用的是父进程的代码和数据(如果子进程需要更改数据,就会在一块单独的空间拷贝一份数据,也就是更改时会创建副本,即写时拷贝)

操作系统中 所有进程具有独立性,不相互影响

你同时用网易云听歌和挂着qq,关闭qq时也不会影响网易云的播放对吧

理解fork

先让我们问问Linux里的man

Linux理解fork()和进程状态详解_第1张图片

函数的返回值类型是pid_t(int),作用是创建子进程

fork()函数的返回值:父进程返回值是子进程的pid,子进程如果创建成功返回0,失败则返回-1

fork函数有两个返回值,父进程一个,子进程一个,父进程调用fork创建子进程,因为代码是共享的,所以两个进程都会return。

test.c//测试代码  注意后面的测试用例都是用这个代码
#include    
#include          
int main()    
{    
printf("i am a process ,pid:: %d\n",getpid());    
int ret=fork();  //ret接收返回值  
if(ret>0)    
{    
 while(1)    
 {    
   printf("i am father,pid:: %d\n",getpid());    
   sleep(1);    
 }    
}    
else    
{    
 while(1)    
 {    
 printf("i am son,pid::%d,my father is %d\n",getpid(),getppid());   
   sleep(1);                                                       
 }    
}    

return 0;    
}   

运行:

Linux理解fork()和进程状态详解_第2张图片

运行时输入 ps axj|head -1&&ps axj|grep test

运行完之后进程被销毁,要看到这个C程序相应的进程就得在运行时输入命令

Linux理解fork()和进程状态详解_第3张图片

显然,创建子进程成功,父子进程交替运行

效果看起来像父子同时运行,是因为CPU切换进程的时间很短,所以几乎就是同时的,这也就是并发(单核CPU)

多核CPU同时进行多个任务,也就是并行

通常用法:和if配合使用,使得一个进程运行不同的程序

从内核的角度,系统是不是多了一个进程?

是的,通过上面的ps命令可以看到显然有两个进程在运行

为什么给子进程创建返回的是0,父进程返回的是子进程的PID

理解一个父亲可以有多个儿子,而每个儿子只有一个父亲,即一个父进程可以有多个子进程,父进程返回的PID更好找儿子

进程=我的程序代码+内核的数据结构(task_struct)

task_struct 是PCB(进程控制块),前面的文章有讲过,里面放着进程的各种信息

这个结构体在源码里也可以找到

进程状态

操作系统下描述的状态

Linux理解fork()和进程状态详解_第4张图片

具体的操作系统Linux下的进程状态

R :运行状态

S :睡眠状态(浅睡眠)

D :磁盘休眠状态(深睡眠)

T :停止状态

t :跟踪状态

Z :僵尸状态

X:死亡状态

运行状态就一定在运行吗?

不一定,在运行队列里也叫运行状态,也就是可执行但还没被调度

换种说法,R状态的意思是我准备好了 可以被CPU调度

S和D的区别

S(可中断的睡眠状态)还可以对外部状态做出反应,就比如你睡觉时还是能被叫醒的

D(不可中断的睡眠状态)保护一些进程不被打断,比如公司上传数据时进程突然被打断了,那损失就大了,D状态就可以预防这种事故发生

注:D状态不能被kill掉

T状态

可以通过kill命令清除进程或者让进程停止

进程停止:kill -19 PID 停止进程

继续进程:kill -18 PID 让停止的进程继续

清除进程 kill -9 PID 清除进程

Linux理解fork()和进程状态详解_第5张图片

Z状态

进程退出: 一般不会立即让操作系统(OS)回收资源

在进程退出的时候,会自动将自己退出的相关信息写入进程的PCB中,这也就是Z(僵尸)状态

在OS或父进程读取完后该进程才算真正死亡,进入X(死亡)状态

创建进程是为了完成任务,比如写入到PCB的信息就会包括任务是否完成等

Linux理解fork()和进程状态详解_第6张图片

什么样的进程杀不掉

僵尸状态(Z)和磁盘休眠(D)不能被杀掉

上图可以看出父进程状态是S(睡眠)状态,按理来说是R状态啊,ps获取的是这个时刻进程的状态,按CPU的运行速度,运行的时间很短,运行一次得睡上一秒,所以获取到的是sleep状态,看到的就会是S状态

被杀掉的进程显示Z状态,出现一个英文单词defunct

image-20220113231825297

看进程状态时,发现有些显示S有些显示S+

带‘+’表示是前台运行,不带是后台运行

前台运行的进程可以输入命令,可以被bash(命令行解释器)识别

后台运行的则不行,后台停止可采用fg命令将后台转到前台再ctrl+c停止程序

./可执行程序 & 表示在后台运行

如./test &

image-20220113233654851

Linux理解fork()和进程状态详解_第7张图片

Linux理解fork()和进程状态详解_第8张图片

孤儿进程 领养人:1

什么是孤儿进程

父进程先被杀掉了,只剩下子进程了

(子进程:坏了,我成孤儿了[doge]

孤儿的领养人:1号进程(PID为1的进程)

1号进程负责回收孤儿进程,上文说过进程死后写入进PCB的信息被父进程或者OS读取才算真正死亡,子进程在父亲死亡后,由1号system进程承担这个责任

1号进程 又称为system/init 进程

image-20220114000346844

这个进程是杀不死的,即kill发送给1号进程的信号会被忽略

领养人选为1号进程,好回收孤儿进程释放的资源(收尸…)

Linux理解fork()和进程状态详解_第9张图片

操作系统的状态和Linux的状态对应图

Linux理解fork()和进程状态详解_第10张图片

末尾

如果有帮助的话麻烦点个赞鼓励一下!

你可能感兴趣的:(linux学习笔记,linux,运维,服务器)