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

进程退出的种类

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

  • 正常退出
    a. 在main()函数中执行return
    b.调用exit()函数。

  • 异常退出
    a.调用abort函数;
    b.进程收到某个信号,而该信号使程序终止。

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

父子进程退出的顺序

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

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

  • 子进程先于父进程终止,而父进程调用了wait函数
    此时父进程会等待子进程结束。

实例

任务描述

试想这样的场景:

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

整个过程如下:

  • 你的朋友先出去;
  • 你先出去,你没有等你的朋友;
  • 你先出去,你在出口等你的朋友。

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

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

编程要求

在主函数的最开始会初始化一个全部变量g_i4event0

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

  • 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 <stdio.h>
#include <stdlib.h>
#include <string.h>  
#include <unistd.h> 
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include<sys/wait.h>

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;
}

 

Logo

更多推荐