进程创建
fork函数初识
在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。
返回值:子进程中返回0,父进程返回子进程id,出错返回-1
进程调用fork,当控制转移到内核中的fork代码后,内核做:
- 分配新的内存块和内核数据结构(task_struct,mm_struct,页表等)给子进程
- 将父进程部分数据结构内容拷贝至子进程
- 添加子进程到系统进程列表当中
- fork返回,开始调度器调度
当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以
当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。但每个进程都将可以开始它们自己的旅程
进程 = 1内核数据结构+2代码和数据
fork创建子进程的时候 是先1还是2呢?
答案是1举个例子我们去大学报名,是档案先去人后面再去
写时拷贝
通常,父子代码共享,但是数据不是是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。
fork调用失败的原因
系统中有太多的进程
实际用户的进程超过了限制
进程终止
想明白:终止在做什么?
- 释放代码,数据(本身就不再被调度了)和内核数据结构
- 但是task_struct 这个内核数据结构会被延期释放,因为要返回子进程的退出信息
进程终止的情况
进程终止的情况有三种
- 代码跑完结果正确
- 代码跑完结果不正确
- 异常退出
main函数的返回值
main函数的返回值,我们称为退出码,关心方要知道进程指向情况怎么。
我们可以通过ehco $?来查看最近一个进程的退出码
对于一个进程来讲 0代表成功 非0表示失败,因为成功我们就不管了,但是失败了要知道是什么情况。刚好非零的数字特别多
退出码含义:
bash获取最近一个进程的退出码,要知道进程的执行情况怎么样?为用户负责。
自定义退出码
异常退出
比如说我们解引用空指针写入数据,会发生segmentation fault(段错误)
其实本质是操作系统给进程了一个信号
我举个例子证明,下面这个代码正常情况会一直运行
但是我们给它一个信号他就会报段错误
异常的时候我们看退出信号是什么就可以判断出是什么异常了
衡量一个进程退出只需要两个数字一个退出码另一个退出信号
如何终止进程
- main函数return 表示进程终止
- 代码任意位置调用_exit(),exit()函数表示进程终止
_exit() 和 exit()的区别
exit()退出的时候会刷新缓冲区而_exit()不会
用_exit()的结果
我们可以得出一个结论缓冲区一定不在操作系统内部,因为_exit()刷新不了缓冲区
进程等待
任何子进程在退出的情况下,一般必须有父进程进行等待。
为什么呢?
- 父进程通过等待解决子进程退出的僵尸问题,回收系统资源
- 获取子进程的退出信息
进程等待的操作
wait
- wait 父进程等待任意一个进程
staus 可以得到进程的退出码和退出信号,前16位没用
后16位开始 0~7位是退出码 第8位没用 ,9~15是退出信号
对于退出码我们只需要 status右移8位 退出码只需要 按位与0x7f(二进制01111 1111)
WIFEXITED(status): 查看是否正常退出
若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 查看退出码的宏
上面位操作得到退出码 还是有点麻烦,我们可以利用系统给的宏WEXITSTATUS得到退出码
waitpid
waitpid 的作用是等待子进程,
参数
- pid:pid = -1时等待任意一个进程,其他就是等待指定的一个进程
- stat_loc 用于保存退出码和退出信号,我们不关心退出码和退出信号的时候可以把它设置为0
- options 用于选择父进程是阻塞等待还是非阻塞等待。WNOHANG时是非阻塞等待其他是0
返回值
- ret > 0: 检查成功
- ret = 0: 检查成功,但子进程还在运行
- ret< 0: 等待失败
非阻塞等待就是父进程等待的过程,可以干其他事情
非阻塞等待的例子:
进程替换
进程替换的函数
这些函数的参数是什么·等下再介绍,我们先来看一个现象
现象
我们发现运行了ls命令 之后没有运行printf了,类似于被夺舍了
原理
将进程中的代码和数据完全替换,没有创建新进程哦,
本质就是进程被加载到内存了
多进程版
对于单一的一个进程,进程替换了原来这个进程就直接没了,大部分场景的时候我们都不希望这样做。
本质是对代码发生了写时拷贝
execl 这些接口的参数
- path:告诉要执行的文件在什么位置
- arg*… 是可变参数,他的参数个数可以不固定,命令行怎么写就怎么传
带p的可以不用传文件路径了,直接在环境变量中找