一、进程退出
正常退出:
1.Main函数调用return
2.进程调用exit(),标准c库
3.进程调用_exit()或者_Exit(),属于系统调用
补充:
1.进程最后一个线程返回
2.最后一个线程调用pthread_exit
异常退出
1.调用abort
2.当进程收到某些信号时,如ctrl+c
3.最后一个线程对取消(cancellation)请求作出响应
二、僵尸进程
父进程等待子进程退出,并收集子进程的退出状态
如果子进程退出状态不被收集,则变成僵死进程(僵尸进程)
wait函数:
status参数:
是一个整型数指针
非空:子进程退出状态放在它所指向的地址中
空:不关心退出状态
如果其所有子进程都还在运行,则阻塞
如果一个子进程以终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回
如果它没有任何子进程,则立即出错返回
waitpid有一个选项,可以使调用者不阻塞。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = fork();
if(pid > 0)
{
wait(NULL);
//waitpid(pid,&status,WNOHANG); //调用者不阻塞,父子进程同时进行,但子进程是僵尸进程
while(1){
printf("cnt = %d\n",cnt);
printf("this is father print,pid = %d\n",getpid());
sleep(1);
}
}
else if(pid == 0)
{
while(1){
printf("this is child print,child pid = %d\n",getpid());
sleep(1);
cnt++;
if(cnt == 3){
exit(0);
}
}
}
return 0;
}
此时,父进程调用wait,参数非空,子进程不会变成僵尸进程。
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
int status = 10;
pid = fork();
if(pid > 0)
{
wait(&status);
printf("child quit,child status = %d\n",WEXITSTATUS(status));
while(1){
printf("cnt = %d\n",cnt);
printf("this is father print,pid = %d\n",getpid());
sleep(1);
}
}
else if(pid == 0)
{
while(1){
printf("this is child print,child pid = %d\n",getpid());
sleep(1);
cnt++;
if(cnt == 5){
exit(3);
}
}
}
return 0;
}
此时wait非空,exit退出码为3,3保存在status中,用宏WEXITSTATUS解析。
三、孤儿进程
父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程
Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
int status = 10;
pid = fork();
if(pid > 0)
{
printf("this is father print,pid = %d\n",getpid());
}
else if(pid == 0)
{
while(1){
printf("this is child print,child pid = %d,my father = %d\n",getpid(),getppid());
sleep(1);
cnt++;
if(cnt == 5){
exit(3);
}
}
}
return 0;
}