fork()
fork是什么?
C语言里的一个创建子进程的函数
作用:创建子进程
创建后有两个进程,一个父亲,一个儿子
父子共享用户代码 而用户数据各自私有一份
共享代码私有数据的目的:维护进程的独立性
创建子进程:子进程的创建是以父进程为模板的,即默认使用的是父进程的代码和数据(如果子进程需要更改数据,就会在一块单独的空间拷贝一份数据,也就是更改时会创建副本,即写时拷贝)
操作系统中 所有进程具有独立性,不相互影响
你同时用网易云听歌和挂着qq,关闭qq时也不会影响网易云的播放对吧
先让我们问问Linux里的man
函数的返回值类型是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; } 运行:
运行时输入 ps axj|head -1&&ps axj|grep test
运行完之后进程被销毁,要看到这个C程序相应的进程就得在运行时输入命令
显然,创建子进程成功,父子进程交替运行
效果看起来像父子同时运行,是因为CPU切换进程的时间很短,所以几乎就是同时的,这也就是并发(单核CPU)
多核CPU同时进行多个任务,也就是并行
通常用法:和if配合使用,使得一个进程运行不同的程序
从内核的角度,系统是不是多了一个进程?
是的,通过上面的ps命令可以看到显然有两个进程在运行
为什么给子进程创建返回的是0,父进程返回的是子进程的PID
理解一个父亲可以有多个儿子,而每个儿子只有一个父亲,即一个父进程可以有多个子进程,父进程返回的PID更好找儿子
进程=我的程序代码+内核的数据结构(task_struct)
task_struct 是PCB(进程控制块),前面的文章有讲过,里面放着进程的各种信息
这个结构体在源码里也可以找到
R :运行状态
S :睡眠状态(浅睡眠)
D :磁盘休眠状态(深睡眠)
T :停止状态
t :跟踪状态
Z :僵尸状态
X:死亡状态
不一定,在运行队列里也叫运行状态,也就是可执行但还没被调度
换种说法,R状态的意思是我准备好了 可以被CPU调度
S(可中断的睡眠状态)还可以对外部状态做出反应,就比如你睡觉时还是能被叫醒的
D(不可中断的睡眠状态)保护一些进程不被打断,比如公司上传数据时进程突然被打断了,那损失就大了,D状态就可以预防这种事故发生
注:D状态不能被kill掉
可以通过kill命令清除进程或者让进程停止
进程停止:kill -19 PID 停止进程
继续进程:kill -18 PID 让停止的进程继续
清除进程 kill -9 PID 清除进程
进程退出: 一般不会立即让操作系统(OS)回收资源
在进程退出的时候,会自动将自己退出的相关信息写入进程的PCB中,这也就是Z(僵尸)状态
在OS或父进程读取完后该进程才算真正死亡,进入X(死亡)状态
创建进程是为了完成任务,比如写入到PCB的信息就会包括任务是否完成等
僵尸状态(Z)和磁盘休眠(D)不能被杀掉
上图可以看出父进程状态是S(睡眠)状态,按理来说是R状态啊,ps获取的是这个时刻进程的状态,按CPU的运行速度,运行的时间很短,运行一次得睡上一秒,所以获取到的是sleep状态,看到的就会是S状态
被杀掉的进程显示Z状态,出现一个英文单词defunct
看进程状态时,发现有些显示S有些显示S+
带‘+’表示是前台运行,不带是后台运行
前台运行的进程可以输入命令,可以被bash(命令行解释器)识别
后台运行的则不行,后台停止可采用fg命令将后台转到前台再ctrl+c停止程序
./可执行程序 & 表示在后台运行
如./test &
什么是孤儿进程
父进程先被杀掉了,只剩下子进程了
(子进程:坏了,我成孤儿了[doge]
孤儿的领养人:1号进程(PID为1的进程)
1号进程负责回收孤儿进程,上文说过进程死后写入进PCB的信息被父进程或者OS读取才算真正死亡,子进程在父亲死亡后,由1号system进程承担这个责任
1号进程 又称为system/init 进程
这个进程是杀不死的,即kill发送给1号进程的信号会被忽略
领养人选为1号进程,好回收孤儿进程释放的资源(收尸…)
如果有帮助的话麻烦点个赞鼓励一下!