进程控制
fork
进程调用fork,当控制转移到内核中的fork代码后,内核做:
- 分配的内存快和内核数据结构给子进程
- 将父进程部分数据结构拷贝到子进程
- 添加子进程到执行列表中
- fork返回后,会开始调度器调度
写时拷贝是按需进行分配内存的表现
fork的时候,父进程希望子进程拷贝自己的部分代码并执行
fork失败的原因:
1.系统中的进程过多
2.实际用户的进程数超过了限制
进程终止
1.情况分类:
- 正常执行完(1.结果正确(0) 2.结果不正确(!0)) -- 退出码(return 0;)并不为零
- 进程异常终止(崩溃) -- 崩溃的本质:进程因为某些原因,导致进程收到了来自操作系统(OS)的信号。
$? : 只会保留最近一次执行的进程的退出码
2.理解进程终止
OS内执行的进程少了一个,代表OS需要释放相应的内核数据结构+代码和数据(如果有独立的)
3.操作方式
main函数return代表整个进程返回,其他函数的return仅仅代表该函数的返回值。
exit(code): code的数值就是退出码,在代码的任何地方调用该函数都表示进程退出!!!在系统调用之前,要检查文件的打开情况,把文件缓冲区中的内容写回文件。在_exit(code)的基础上做了一定的包装。
_exit(code):直接使进程停止运行,清楚其使用的内存空间,并销毁其在内核中的各种数据结构。
进程等待
1.为什么会有进程等待
- 子进程退出,父进程对其不管不顾,会出现僵尸进程,可能出现僵尸进程,导致内存泄漏(目前一定要做的)
- 获取子进程执行所得到的结果(必要的情况下)
2.什么是进程等待
父进程等待子进程退出的过程
等待:就是通过系统调用,获取子进程退出码或者退出信号的方式,顺便解决内存泄漏的问题
3.怎么进行进程等待(wait/pidwait)
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status)
返回值:
成功返回并等待进程pid,失败返回-1。
输出型参数:
获取子进程退出状态,不关心可以直接设置NULL。
#include<sys/types.h>
#include<sys/wait.h>
pid_ t waitpid(pid_t pid, int* status, int options)
pid > 0:表示等待指定的进程
pid = 1:等待任意一个子进程,与wait等效
int* status;
1.输出型参数
2.期望获取的是子进程的状态 -- 信号+退出码
不要当做一个完整的整数,而应该看做位图 -- 用一个或者多个比特为来表示状态
status:有32个比特位
父进程在等待子进程结束的时候,父进程在干嘛?
父进程只能一直在调用waitpid进行等待 -- 阻塞等待,不是运行状态 -- 在阻塞队列中
如何不在waitpid卡住?
将最后一个参数改为 WNOHANG。
做一次状态检查,如果用了很多次检测:非阻塞轮询。