linux进程等待wait()实例

在Linux系统中,进程的生命周期内主要包含:进程就绪、进程执行、进程等待和进程退出

  • 就绪转执行
    处于就绪状态的进程,当进程调度程序为之分配了处理机(CPU)后,该进程便由就绪状态转变成执行状态。

  • 执行转就绪
    处于执行状态的进程在其执行过程中,因分配给它的一个时间片已用完或更高优先级的进程抢占而不得不让出处理机,于是进程从执行状态转变成就绪状态。

  • 执行转等待
    正在执行的进程因等待某种事件发生而无法继续执行时,便从执行状态变成等待状态。

  • 等待转就绪
    处于阻塞状态的进程,若其等待的事件已经发生,于是进程由等待状态转变为就绪状态。

  • 执行转退出
    进程执行完毕,撤销而退出。

其中,进程等待是进程控制的关键,也是本关的重点。

进程等待的原因

进程控制块(PCB)是进程在整个运行过程中非常重要的一个数据结构,里面包含以下几种信息:

  • 进程描述信息;
  • 进程控制信息;
  • 资源信息;
  • 现场保护信息。

进程终止或者退出的时候,进程会关闭所有文件描述符,释放用户空间分配的内存,但是PCB却会暂时保留。假如进程正常终止,PCB里面就记录进程的退出状态;如果是异常终止,那么PCB里面存放着导致该进程终止的信号。

子进程的退出状态必须由父进程回收,也就是说,父进程必须得等待子进程退出后再自己退出,否则子进程会变成僵尸进程(没有任何可执行代码,不会被调度,只有一个进程描述符用来记录退出的状态,除此之外不再占用其他任何资源)。

wait函数

  1. #include
  2. #include
  3.  
  4. pid_t wait(int* status);

参数:status,整型指针,指向的地址即存放退出子进程的退出状态,不关心可以设为NULL

等待方式是阻塞式等待,一旦子进程退出,父进程就会立刻收到SIGCHLD信号。

注意:父进程调用wait,是等待任意一个已经退出的子进程,只要是有子进程退出了,那么就获取子进程退出状态然后返回。

waitpid函数

  1. #include
  2. #include
  3.  
  4. pid_t waitpid( pid_t pid, int *status ,int options);

参数详解:

  • pid:希望等待退出的子进程的进程号;

  • status:整型指针,指向的地址即存放退出子进程的推出状态,不关心可以设为NULL

  • options:设置为0,代表阻塞式等待,如果设置为WNOHANGwaitpid发现没有已经退出的子进程可以收集,就返回0,此时是非阻塞式等待。

返回值:

返回0表示没有已经退出的子进程;返回正值,表示有已经退出的子进程。

任务描述

试想这样的场景:

你和你的树懒一起到外面吃午餐,你吃的比较快,但是要等待树懒吃完后才能一起走。

整个过程如下:

  • 你和树懒开始就餐;
  • 你需要等待树懒吃完后再一起走。

以进程等待代替整个过程, 对于上述过程可以理解为创建子进程->等待子进程退出->主进程退出。

本关任务:

 

  • 创建子进程;
  • 等待子进程退出。

编程要求

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

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

创建子进程,创建完后,将g_i4event置为1

子进程等待3s,然后子进程退出;

父进程等待一秒,将g_i4event置为2;然后等待子进程退出,父进程获取子进程退出的状态后将g_i4event置为3

process_wait采用wait函数,process_waitpid采用waitpid函数。

测试样例:

测试输入:1

预期输出:
You and Sloth go to have lunch!
You have finished your meal!You need wait the sloth
Sloth have finished your meal! You and sloth will go home.

测试输入:2

预期输出:
You and Sloth go to have lunch!
You have finished your meal!You need wait the sloth
Sloth have finished your meal! You and sloth will go home.

测试说明

测试过程:

 

  • 用户补全框架内的代码,实现功能性代码;

  • 接着根据程序的输出判断程序是否正确。

  • 不要在代码中使用printf等进行输出,以免引起结果判断错误。

 

#include 
#include 
#include   
#include  
#include 
#include 
#include 
#include 
#include

pthread_t pid;
int g_i4event = 0;

int process_wait(void);
int process_waitpid(void);

int g_i4event;
int process_wait(void)
{
    /********Begin********/
    int rc = fork();
    g_i4event=1;
    if(rc==0)
    { 
        sleep(3);
    }
    else
    {
        sleep(1);
        g_i4event=2;
        wait(NULL);
        g_i4event=3;

    }
    return 0;
    
    /*********End*********/
}

int process_waitpid(void)
{
    /********Begin********/
     int rc = fork();
     g_i4event=1;

    if(rc==0)
    { 
        sleep(3);
    }
    else
    {
        sleep(1);
        g_i4event=2;
        waitpid(rc,NULL,0);
        g_i4event=3;

    }
    return 0;
    
    /*********End*********/
}

void *detect(void *arg)
{
	int count = 0;
	while (1)
	{
	    switch(g_i4event)
	    {
	    	case 0:
	    	    break;
	    	case 1:
	    	    count ++;
	    	    printf("You and Sloth go to have lunch!\n");
	    	    break;
	    	case 2:
	    	    count ++;
	    	    if(2 == count)
	    	    {
	    	    	printf("You have finished your meal!You need wait the sloth\n");
	    	    }
	    	    else
	    	    {
	    	    	printf("You have not finished your meal!\n");
	    	    	return NULL;
	    	    }
	    	    break;
	    	case 3:
	    	    count ++;
	    	    if(3 == count)
	    	    {
	    	    	printf("Sloth have finished your meal! You and sloth will go home.\n");
	    	    }
	    	    else
	    	    {
	    	    	printf("Sloth have not finished your meal!\n");
	    	    }
	    	    return NULL;
	    	default:
	    	    break;
	    }
	    g_i4event = 0;
	    usleep(10 * 1000);
	}
    return NULL;
}

#define WAITCMD 1
#define WAITPIDCMD 2
int main(int argc, char *argv[])
{
	char cmd[32] = {0};
	scanf("%s", cmd);
	pthread_create(&pid, NULL, detect, NULL);
	if(WAITCMD == atoi(cmd))
	{
		process_wait ();
	}
    else if(WAITPIDCMD == atoi(cmd))
	{
		process_waitpid ();
	}
    pthread_join(pid, NULL);
	
    return 0;
}

 

你可能感兴趣的:(os,os)