一. 进程退出的情况
1.1 程序运行完毕
结果正常: 默认情况下的退出码为0
结果不正常: 默认退出的退出码为大于0的整数,每一个数字代表对应的情况
补充: 从
main
函数返回,调用exit
或者_exit
,都可以获取进程的退出码。_exit
是系统调用接口,不会清理文件缓冲区,关闭流。exit
会清理缓冲区和关闭流。在命令行输入echo $?
可以查看最近一次进程的退出码,在C程序调用strerror(i)
,会返回退出码i
代表的含义
1.2 程序异常终止
接收到信号,被强制终止。在命令行执行
kill -l
可以查看有哪些终止的信号。
二. 进程等待
2.1 为什么需要等待
- 子进程退出,父进程没有进行等待,子进程就会变成僵尸进程,进而造成内存泄露。
- 父进程需要通过等待的方式去回收子进程的资源,获取子进程退出的信息。
2.2 进程等待的方法
2.21 wait方法
// 1. pid_t wait (int *status);
// status是用来保存子进程退出的信息
// 一共是32个比特位
// 低7位用来存放终止信号,程序接收到异常信号就会被强制退出,正常退出终止信号位0
// 低第9位到低第16位存放的是退出状态码,也就是exit,和return发送的退出码
int main()
{
pid_t ret = fork();
if (ret < 0)
{
perror("fork");
}
if (0 == ret)
{
// child
int a = 5;
a /= 0;
while (a--)
{
printf("%d\n", a + 1);
sleep(1);
}
exit(100);
}
// parent
printf("wait begin\n");
int status = 0;
//pid_t id = wait(NULL);
pid_t id = wait(&status);
if (-1 == id)
{
printf("wait failed\n");
exit(1);
}
printf("success, pid is %d\n", id);
//printf("exit_code --> %d : signal --> %d\n", (status >> 8) & 0xff, status & 0x7f);
// WIFEXITED(status),如果进程正常退出返回true
if (WIFEXITED(status))
{
// WEXITSTATUS(status),返回进程的退出码,进程正常退出才会有效
printf("eixt_code --> %d\n", WEXITSTATUS(status));
}
else
{
printf("A signal has been picked up\n");
// WTERMSIG(status),返回终止进程的信号,进程被信号终止的情况下才会有效
printf("signal --> %d\n", WTERMSIG(status));
}
return 0;
}
2.22 waitpid方法
// 2. pid_t waitpid(pid_t pid, int* status, int options);
// pid 是需要等待的子进程的pid, 传-1过去表示等待任何一个子进程,也可以传具体等待的子进程pid
// status 跟上面的一样
// options 表示等待的方式,0为阻塞等待, WNOHANG为非阻塞等待
int main()
{
pid_t ret = fork();
if (ret < 0)
{
perror("fork");
}
if (0 == ret)
{
// child
int a = 5;
while (a--)
{
printf("%d\n", a + 1);
sleep(1);
}
exit(0);
}
// parent
// 阻塞等待
/*
printf("wait begin\n");
//pid_t id = waitpid(-1, NULL, 0);
pid_t id = waitpid(ret, NULL, 0);
if (-1 == id)
{
printf("wait failed\n");
exit(1);
}
printf("success, pid is %d\n", id);
*/
printf("wait begin\n");
while (1)
{
// 非阻塞等待
pid_t id = waitpid(ret, NULL, WNOHANG);
if (-1 == id)
{
printf("wait failed\n");
break;
}
else if (0 == id)
{
printf("do my thing\n");
}
else
{
printf("success! The child process has exited\n");
break;
}
sleep(1);
}
return 0;
}