一、进程终止
main函数的返回值也叫做进程的退出码,一般0表示成功,非零表示失败。我们也可以用不同的数字来表示不同失败的原因。
echo $?//打印最近一次进程执行的退出码
而作为程序猿,我们更需要知道的是错误码所代表的错误信息,转化方法有以下两种:
1.使用语言和系统自带的方法进行转化
2.自定义
strerror
所以进程代码执行情况大致可以分为正确、不正确、或者代码没有执行完,进程出异常了。
所以我们判断进程最终的执行结果先要判断它是否出异常没有执行完,然后才能判断是否退出的结果正确与否。
进程退出是收到了异常信号。
不同的信号编号表明进程异常的原因。
任何进程最终的执行情况,我们可以使用两个数字表明具体的执行情况。
第一种情况就表明没有异常结果正确
第二种第四种都表示进程出异常
第三种表示退出结果不正确。
exit
我们也可以通过exit直接终止进程,status表示退出码。
在我们进程中,任意地方调用都可以实现进程退出。
_exit和exit的区别就是exit支持刷新缓冲区,_exit不支持。而终止进程是只有操作系统才可以办到的事情,exit作为库函数内部是封装了系统调用_exit 。而例如scanf和printf也是如此,内部都封装了系统调用。经过封装后,语言的可移植性和跨平台性都可以得到提升。
二、进程等待
2.1进程等待的必要性
2.2进程等待的方法
wait方法
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
wait在等待时默认进行阻塞等待。
任意等待一个子进程。
在进程中父进程要进行最后退出,因为它需要进行代码回收。
pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进
程的ID。
可经过编译后才发现最后status是256而不是1.
这是因为status并不是一个单纯的四字节整数,因为status中需要存放两个数字:1.退出码2、退出信号,所以status有自己的格式。我们只考虑它的低16位。
任何进程的最终执行情况,我们可以使用两个数字表明具体执行的情况
而刚刚的写法导致最终status中存储如下图的内容即256
3.3wait_pid的非阻塞等待方式
依旧是上文中的代码,父进程除了进行阻塞等待,还可以进行非阻塞等待
而非阻塞状态下,需要去反复查询子进程状态,是一种基于非阻塞的轮询访问。优点是在当调用wait_pid去轮询期间,父进程可以去继续执行其他代码,而不是一直处于阻塞状态去等待。
根据上图代码和wait_pid的用法,可以将父进程部分代码改为非阻塞状态的写法。