在Linux系统中,当进程退出时,必须释放它所拥有的资源,并通过某种方式告诉父进程。进程的退出一般是显示或隐式地调用了eixt(),或者接受了某种信号。不管是由于什么原因退出,最终都调用了do_exit。

进程退出的种类

Linux下进程的退出分为正常退出和异常退出两种。

正常退出

a. 在main()函数中执行return;

b.调用exit()函数。

异常退出

a.调用abort函数;

b.进程收到某个信号,而该信号使程序终止。

不管是哪种退出方式,系统最终都会执行内核中的同一代码。这段代码用来关闭进程用到的文件描述符,释放它所占用的内存和其他资源。

父子进程退出的顺序

父进程先于子进程终止:

此种情况下,父进程会变成孤儿进程。当父进程先退出时,系统会让init进程接管子进程。

子进程先于父进程终止,而父进程又没有调用wait函数

此种情况子进程进入僵死状态,并且会一直保持下去直到系统重启。子进程处于僵死状态时,内核只保存进程的一些必要信息以备父进程所需。此时子进程始终占有着资源,同时也减少了系统可以创建的最大进程数。

子进程先于父进程终止,而父进程调用了wait函数

此时父进程会等待子进程结束。

实例

任务描述

试想这样的场景:

你的朋友和你一起到逛超市,逛的途中你们分散了,你们各自走出超市出口的先后顺序不同有三种情况。

整个过程如下:

你的朋友先出去;

你先出去,你没有等你的朋友;

你先出去,你在出口等你的朋友。

以进程退出的三种可能性代替这三种情况:

父进程先退出;

子进程先退出,父进程没有调用等待函数;

子进程先退出,父进程调用了等待函数。

编程要求

在主函数的最开始会初始化一个全部变量g_i4event为0。

本关的编程任务是补全右侧代码片段中三段Begin至End中间的代码,具体要求如下:

father_son中,创建子进程后,将g_i4event置为1;父进程睡眠一秒后将g_i4event置为2,接着直接退出;子进程睡眠两秒后直接退出;

son_father_nowait中,创建子进程后,将g_i4event置为1;子进程睡眠一秒后直接退出;父进程睡眠两秒后将g_i4event置为3直接退出;

son_father_wait中,创建子进程后,将g_i4event置为1;子进程睡眠一秒后直接退出;父进程等待子进程退出,然后睡眠一秒,随后将g_i4event置为4退出。

测试样例:

测试输入:1

预期输出:

You and your friend go to the supermarket!

Your friend go out first!

测试输入:2

预期输出:

You and your friend go to the supermarket!

You go out first!You will not wait for your friend!

测试输入:3

预期输出:

You and your friend go to the supermarket!
You go out first! You will wait for your friend!
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
pthread_t pid;
int g_i4event = 0;
int father_son(void);
int son_father_nowait(void);
int son_father_wait(void);
int father_son(void)
{
/********Begin********/
int rc=fork();
g_i4event=1;
if(rc==0)
sleep(2);
else
{
sleep(1);
g_i4event=2;
}
return 0;
/*********End*********/
}
int son_father_nowait(void)
{
/********Begin********/
int rc=fork();
g_i4event=1;
if(rc==0)
{
sleep(1);
}
else
{
sleep(2);
g_i4event=3;
}
return 0;
/*********End*********/
}
int son_father_wait(void)
{
/********Begin********/
int rc=fork();
g_i4event=1;
if(rc==0)
{
sleep(1);
}
else
{
wait(NULL);
sleep(1);
g_i4event=4;
}
return 0;
/*********End*********/
}
void *detect(void *arg)
{
int count = 0;
while (1)
{
switch(g_i4event)
{
case 0:
break;
case 1:
count ++;
printf("You and your friend go to the supermarket!\n");
break;
case 2:
count ++;
if(2 == count)
{
printf("Your friend go out first!\n");
}
return NULL;
case 3:
count ++;
if(2 == count)
{
printf("You go out first!You will not wait for your friend!\n");
}
return NULL;
case 4:
count ++;
if(2 == count)
{
printf("You go out first! You will wait for your friend!\n");
}
return NULL;
default:
break;
}
g_i4event = 0;
usleep(10 * 1000);
}
return NULL;
}
#define FATHER_SON 1
#define SON_FATHER_NOWAIT 2
#define SON_FATHER_WAIT 3
int main(int argc, char *argv[])
{
char cmd[32] = {0};
scanf("%s", cmd);
pthread_create(&pid, NULL, detect, NULL);
if(FATHER_SON == atoi(cmd))
{
father_son ();
}
else if(SON_FATHER_NOWAIT == atoi(cmd))
{
son_father_nowait ();
}
else if(SON_FATHER_WAIT == atoi(cmd))
{
son_father_wait ();
}
pthread_join(pid, NULL);
return 0;
}