一、结束进程:
我们可以通过exit()或者_exit()函数来结束当前进程。
(一)
- 所需头文件:
#include <stdlib.h>
- 函数:
void exit(int value);
- 功能:
结束调用此函数的进程
- 参数:
status:返回父进程的参数(低8为有效)
- 返回值:
无
(二)
- 所需头文件:
#include <unistd.h>
- 功能:
结束调用此函数的进程
- 参数:
status:返回父进程的参数(低8为有效)
- 返回值:
无
注意:exit()和_exit()函数功能和用法是一样的,无非是所包含的头文件不一样,一个是库函数,一个是系统函数。
区别如下:
我们可以通过下面这个例子来验证:
test.c
#include<stdio.h>
#include <stdlib.h>
int main()
{
printf("hello world!");
exit(0);
while(1);
return 0;
}
运行结果:
test1.c
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world!");
_exit(0);
while(1);
return 0;
}
运行结果:
注意:这里printf中的内容不能带\n,\n会刷新。
二、等待进程结束:
当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号,相当于告诉父亲哪个子进程挂了,父进程通过wait()或waitpid()函数等待子进程结束,获取子进程结束时的状态,同时回收资源。
wait()和waitpid()函数的功能一样,区别在于,wait()函数会阻塞,waitpid()可以设置不阻塞,waitpid()还可以指定等待哪个子进程结束。
(一)
- 所需头文件:
#include <sys/types.h>
#include <sys/wait.h>
- 函数:
pid_t wait(int* status);
- 功能:
- 等待任意一个子进程结束,如果任意一个子进程结束了,此函数就回收该子进程的资源
- 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件、占用的内存等。但是仍然会保留一定的信息,这些信息主要指进程控制块的信息(包括进程号、退出状态、运行时间等)。
- 调用wait()函数的进程会挂起(阻塞),直到它的一个子进程退出或者收到一个不能被忽视的信号时才被唤醒(继续往下执行)
- 若调用进程没有子进程,则函数立即返回,若它的子进程已经结束,该函数同样会立即返回,并且回收该子进程的资源。
总言之:wait()函数的主要功能为回收已经结束子进程的资源
- 参数:
- status:进程退出时的状态信息。
- 如果参数status的值不是NULL,wait()就会把子进程退出时的状态取出并存入其中,这是一个整数值(int),指出了子进程时正常退出还是被异常结束的。
- 这个退出在一个int中包含了多个字段,不能直接使用,需要使用宏定义取出其中每个字段。
WIFEXITED(status);//如果子进程是正常终止的,取出的字段非0
WEXITSTATUS(status);//返回子进程的退出状态,退出状态保存在status变量的8~16位,在用此宏前先用WIFEXITED判断子进程是否正常退出,正常退出才可以使用此宏。
- 返回值
- 成功:已经结束子进程的进程号
- -1
从本质上讲:系统调用waitpid()和wait()的作用是完全相同的,但waitpid()多出了两个有用户可控制的参数pid和options,从而可以灵活使用。
(二)
- 函数:
pid_t waitpid(pid_t pid,int* status,int options);
- 功能:
等待子进程终止,如果子进程终止了,此函数回收子进程的资源。
- 参数:
- pid:参数pid的值有以下几种类型:
(1)pid>0:等待ID等于pid的子进程
(2)pid=0:等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会等待
(3)pid=-1:等待任一子进程,此时waitpid和wait一样
(4)pid<-1:等待指定进程组中的任一子进程,这个进程组的ID等于pid的绝对值 - status:进程退出时的状态信息,和wait()用法一样
- options:options提供了一些二外的选项来控制waitpid()
(1) 0:同wait(),阻塞父进程,等待子进程退出。
(2) WNOHANG:没有任何已经结束的子进程,则立即返回
(3) WUNTRACED:如果子进程暂停了则此函数马上返回,并且不予理会子进程的结束状态。 - 返回值:waitpid()的返回值比wait()稍微复杂一些,三种情况:
(1)当正常返回时,返回收集到的已经结束的子进程的进程号。
(2)如果设置了WNOHANG,而调用中waitpid()发现没有已退出的子进程可等待,则返回0
(3)如果调用出错,则返回-1,这是error会被设置成相应的值以示错误存在。
测试例子:
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
pid_t pid;
pid = fork();
if(pid<0)
{
perror("fork error");
exit(0);
}
else if(pid == 0)
{
//子进程
int i;
for(i = 0;i<5;++i)
{
printf("this is son process\n");
sleep(1);
}
_exit(2);
}
else
{
//父进程
int status = 0;
wait(&status);
if(WIFEXITED(status) != 0)
{
printf("son process return %d\n",WEXITSTATUS(status));
}
printf("this is father process\n");
}
return 0;
}
运行结果: