Linux 下父子进程的调度的理解

fork()
为什么要fork()创建子进程?

1 一个进程希望能执行不同的代码段
2 一个进程希望复制自己,同时父子进程执行不同的代码段。

规则: 父进程为模板 ,创建子进程
1 将父进程的PCB复制一份 稍加修改作为子进程的PCB
2 将父进程的虚拟地址空间空间拷贝一份,作为子进程的地址空间

采用写时拷贝的方式,写时拷贝效率高,用到哪,拷贝哪。其实就是偷懒的拷贝方式。
开销 进程 >线程 > 协程
fork函数为调用函数,上边肯定还有库

3 fork会在父子进程中分别返回,

**父进程返回子进程的Pid  ,子进程返回0.**  
即 我们的  if  else 判断 fork()的返回值
    父子进程执行顺序由调度情况决定。

4对于 父子进程的理解

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

父进程先结束 所以先打印两个 ,子进程后结束,打印6个

假入我们fflush(stdout)一下 ,
刷新了缓冲区 在这里插入图片描述

缓冲区被刷新(清空),当然6个了。

扫描二维码关注公众号,回复: 10013925 查看本文章

进程的终止:
1 代码执行完,结果正常退出
2 代码自行完,结果不正常退出
3 代码未执行完,异常退出

执行完时,main 函数的返回值作为进程的返回码

默认 0 为进程正常退出,默认非0异常退出。
$?是bash的一个特殊变量 ,表示上个命令对应进程的退出码

如何查看 echo $?在这里插入图片描述
这个码不能为负,范围 0-255

exit也能终止进程
也可以判断进程的正常或者异常退出
头文件为stdlib.h

注意 : exit表示让进程结束 ,而return 代表让函数结束

exit() 库函数
_exit() 系统调用 头文件"unistd.h",他不会刷新缓冲区

exit 本质上调用了_exit,但也有点区别;
0 调用用户函数
1 exit退出时会关闭流 并 fflush () ;
2 调用结束函数

刷新缓冲区的操作 :
1、\n
2 main 函数推出
3 ffush(stdout);
4 调用exit()
在这里插入图片描述在这里插入图片描述
mian()函数结束,也可以通过特殊操作再执行一些过程;
atexit() 它先告诉操作系统给本进程注册一个退出清理函数,

atexit()这个函数 进程退出之前再执行;

;当main函数结束,再执行一个函数,它的参数为一个函数指针(函数名);

下面看一看解决僵尸进程的科学的方法

进程等待

wait
头文件为"sys/wait.h"
1 参数是输出型参数,表示退出码(正常/异常)退出
2 返回值是子进程的PID
3 阻塞式等待,一直等到子进程结束才返回

获取子进程的status
1 wait 和waitpid 都有一个status参数,该参数是一个出型参数,由操作系统填充
2 如果传递NULL,表示不关心子进程的退出状态信息,否则 ,系统就会根据参数将状态信息反馈给父进程;
3 status 不能简单的当作整数来看,可以当作位图来看,我们只研究status的低16位

正常终止 : 0-7位 均为0 , 8-15位表示状态信息
被信号所杀 (异常终止): 0-6位存终止信号 第7位是一个core Dump标志 8-15 位未用
在这里插入图片描述
在这里插入图片描述

1 一个wait()只回收一个进程,wait少了 ,会造成僵尸进程(内存泄漏 );ps aux |grep test可以看到 Z状态的进程,
wait()调用次数要等与子进程个数
wait少了 ——————————僵尸进程(内存泄漏)
wait多了——————————wait()出错

2如果有多个子进程,任何一个子进程结束都会触发wait的返回

waitpid
waitpid 只等特指的子进程,行为和wait非常相似,当参数为(-1,NULL,0)就和wait()一样了;
pid_t waitpid(pid_t pid,int* status,int options=0)
非阻塞式:
waitpid 的第三个参数为(WNOHANG)
waitpid(ret,NULL,WNOHANG);
轮询式的wait好处: 灵活控制代码, 利用等待时间做别的事(阻塞式是一直在等)
坏处: 是代码写起来复杂

发布了90 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44030580/article/details/103526493