fork函数
fork函数是创建一个子进程,之前用过。
#include <unistd.h> pid_t fork(void);
返回值:自进程中返回0,父进程返回子进程id,出错返回-1。
进程拥有独立性,fork之后就变成了两个程序,父子进程共享后边的代码。
那么为什么给父进程返回的就是子进程的pid,而给子进程返回的就是0呢?
就好比孩子只能有一个亲生的父亲,而一个父亲可以拥有很多亲生孩子,每个孩子都是独立不同的。
fork函数是在什么时候创建的子进程呢?
pid_t fork() { 1.创建PCB 2.赋值 3.创建进程地址空间 4.赋值 5.创建并设置页表 6.子进程放入进程队列//这里才是创建成功一个进程,也是分流的地方 7......... return pid;//返回的时候核心代码已经执行完毕了 }
也就是说fork返回两个值是因为返回之前就已经创建好新进程了。
返回的本质就是写入,谁先返回谁先写入id,因为进程的独立性,然后就会发生写时拷贝。
fork失败的原因
系统拥有太多个进程超过了用户进程的限制就会失败。
进程终止
退出码
在写C/C++的时候,我们在main函数是程序的开始,但是最后一个位置会写return 0;
这也就代表一个程序的退出,至于为什么要写return 0,而不是返回其他的,亦或者是不写都可以,因为返回uid这个数字是退出码,0是正常退出的意思,因为正确只有一个,不会管你怎么成功,但是失败就会找失败的原因再去改正。
echo $?是查看最近进程的退出码,上一个写的进程退出码是1,再查一次就是echo $?的退出码,是0.
退出码可以自定义,也可以使用系统的映射关系,这里不太推荐。
这个之前用过:
然后来看看里面数字对应的错误信息
注意:如果程序异常退出码也无意义。
常见的退出方式
上面说了在mian函数中调用return就是进程退出。
C语言和操作系统还提供了两个函数退出进程:
这是C语言提供的一个函数,只要使用就会退出当前进程,参数是退出码。
无论是在哪个位置,或者是后面有多少代码。
还有一个系统级别调用的是_exit,作用几乎相同:
系统调用的并没有打印。
这是C语言提供的,过了两秒钟就打印出来了。
这说明:
exit 终止进程后会主动刷新缓冲区。
_exit 终止之后不会主动刷新缓冲区。
那么这个缓冲区在哪里呢?
exit会刷新缓冲区,但是系统不会,也就是说位置在系统调用和库函数之间,具体的以后说。
进程等待
什么是进程等待,为什么要进程等待
之前说过僵尸进程会导致内存泄漏,因为他的资源无法回收,所以就需要等待子进程结束然后来保存资源给父进程,通过获取子进程退出信息知道是否成功退出。
首先来看两个等待进程的函数。
wait/waitpid:
status参数是拿该进程的退出结果。
options参数是传入阻塞和非阻塞状态。
pid_t是返回进程的pid,返回-1代表失败。
wait
这个程序10-15秒是僵尸进程,15s之后就会被回收,这个时候子进程就不是僵尸状态了。
waitpid
在举例之前首先说一下status:
一个程序终止有三种情况,代码运行完毕,结果正确和不正确,还有没运行完,出异常了。
这个时候status是获取他们这个信息的,并且它是拥有自己的位图结构的。
一共有32个比特位,其中重要的只有16个比特位:
终止信号是一个进程出异常了会受到终止信号,暂时用来判断进程是否正常退出。
退出状态是看结果是否正确。
这个是等待的过程,其实就是status去PCB找信号和退出码。
总结来说:status让操作系统释放掉僵尸状态,然后获取进程的退出结果。
但是如果让我们自己去求信号和退出码很麻烦,所以Linux提供了一些操作的宏,重点说两个:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)


















