本文属于牛客网上的一个项目笔记:Linux高性能服务器开发课
上一章介绍了创建子进程和exec函数族,这一章介绍进程退出,和回收,僵尸进程和孤儿进程。
进程退出
进程退出函数有两个
函数原型:
#include<stdlib.h>
void exit(int status);//函数库
void _exit(int status);//系统自带
调用exit函数后,该进程会结束,并且设置status。
参数:status传出参数,表示程序结束时的状态。
孤儿进程
如果父进程结束了,子进程还没有结束,那么这个子进程就会变成孤儿进程,这个时候init进程会成为其父进程,来帮助回收子进程的资源。
孤儿进程没有危害,因为他有继父!
僵尸进程
每个进程包括内核区和用户区,当程序结束时,用户区会自动释放,但是内核区需要父进程帮助回收,如果这时候父进程没有回收子进程的内核区,那么该进程就会变成僵尸进程。
僵尸进程会占用资源,有害。可以通过wait()或者waitpid()回收。
进程回收
原型:wait()
#inlcude <sys/wait.h>
pid_t wait(int *wstatus);
功能:阻塞等待任意一个子进程结束,如果任意一个子进程结束,此函数会回收其资源
参数: int *wstatus
进程退出时的状态信息会被记录,这是一个传出参数。
返回值: 成功返回被回收子进程的pid
失败(所有的子进程都结束,或者调用失败)返回-1
注:调用wait()函数的进程会被阻塞挂起,直到有一个子进程退出,或收到一个不能被忽略的信号。
用例:
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid;
for(int i=0;i<5;i++){
pid = fork();
//这是为了避免在子进程中创建子进程。
if(pid == 0){
break;
}
}
if(pid > 0){
// 父进程
while(1){
printf("父进程的%d\n",getpid());
pid_t ret = wait(0);
if(ret != -1){
printf("子进程结束-资源已回收--子进程的PID是%d\n",ret);
}else{
printf("子进程全部结束-资源已全部回收\n");
}
sleep(1);
}
}else if (pid == 0)
{
// 子进程
printf("子进程的%d\n",getpid());
}
}
原型:waitpid()
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:回收指定PID的进程,并且可以设置是否阻塞(options)
参数:
pid:>0 回收id = pid的子进程,
=0 回收当前进程组(PGID)的所有子进程,
=-1 回收所有的子进程,相当于wait(),
<-1 回收指定进程组(PGID=-pid)中的的子进程(绝对值)
options:设置阻塞或非阻塞 0 阻塞 WNOHANG 非阻塞
返回值:
>0 返回子进程的pid
=0 非阻塞状态时 表示还有子进程活着
=-1 错误 或者 没有子进程
用例:
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid;
for(int i=0;i<5;i++){
pid = fork();
if(pid == 0){
break;
}
}
if(pid > 0){
// 父进程
while(1){
printf("父进程的%d\n",getpid());
int st;
pid_t ret = wait(&st);
if(ret != -1){
printf("子进程结束-资源已回收--子进程的PID是%d\n",ret);
}else{
printf("子进程全部结束-资源已全部回收\n");
}
sleep(1);
}
}else if (pid == 0)
{
// 子进程
printf("子进程的%d\n",getpid());
}
}