• 进程控制(四)


    wait和waitpid函数

    • wait函数是waitpid函数的简单版本

    • 在多进程处理时,用户可能需要用到有关进程等待的操作,这种等待可以是进程组成员间的等待,也可以是父进程对子进程的等待

    • 在一个进程调用了exit之后,该进程并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构。这时的处理方法之一就是使用进程等待的系统调用wait和waitpid

    wait和waitpid的函数原型是:

    #include <sys/types.h>
    #include <sys/wait.h>
    pid_t wait(int *status);
    pid_t waitpid(pid_t pid,int *status,int options);
    
    • 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止
    • 在调用了exit函数之后,一个正常的进程变成了僵尸进程,进程处于僵尸状态,但它并没有释放它的内存资源一些重要信息(进程是否正常退出等),可以用wait和waitpid来抓住这些信息(收尸员)
    • 参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果程序员对这个子进程是如何死掉的毫不在意,而只是想把这个僵尸进程消灭掉,(事实上绝大多数情况下,程序员们都会这样想),这时就可以设定这个参数为NULL,就像下面这样:
      pid = wait(NULL);
    • 返回值:如果成功,wait会返回被收集的子进程的ID,如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD

    下面例子体验一下wait函数的调用,wait_example.c:

    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    int main(void)
    {
    	pid_t pc,pr;
    	if((pc = fork())<0)
    	{
    		printf("error in fork!");
    		exit(1);
    	}
    	else if(pc == 0)
    	{
    		printf("this is child process with pid of %d
    ",getpid());
    		sleep(10);
    	}
    	else
    	{
    		pr = wait(NULL);
    		printf("I catched a child process with pid of %d
    ",pr);
    	}
    	exit(0);
    }
    
    
    运行结果:
    hyx@hyx-virtual-machine:~/test$ ./wait_example
    this is child process with pid of 13047
    (等待10秒)
    I catched a child process with pid of 13047
    
    • 本质上讲,waitpid和wait作用完全相同,但waitpid多出了两个可由用户控制的参数——>pid和options,从而为用户编程提供了一种更为灵活的方式。waitpid可以用来等待指定的进程,可以使进程不挂起而立刻返回,参数pid用于指定所等待的进程,其取值及相应的含义如下表:

        参数pid取值及其含义
      
        pid取值			含义
        pid > 0			只等待进程ID为pid的子进程,不管其他已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就一直等待下去
        pid=-1			等待任何一个子进程退出,没有任何限制,此时waitpid等价于wait
        pid=0			等待同一个进程组中的任何子进程,如果某一子进程已经加入了别的进程组,waitpid则不会对它做任何理睬
        pid<-1			等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值
      
    • 参数options提供了一些额外的选项来控制waitpid,目前在Linux中只支持WNOHANGWUNTRACED
      两个选项,这是两个常数,如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等待下去。而WUNTRACED参数,由于涉及到一些跟踪调试方面的知识,加之极少用到,先不做了解。可以用"|"运算符把它们连接起来使用,比如:

      ret = waitpid(-1,NULL,WNOHANG|WUNTRACED);

    • 如果不想使用它们,也可以把options设为0,如:

      ret = waitpid(-1,NULL,0);

    一个关于waitpid的例子,waitpid_example.c:

    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    int main(void)
    {
            pid_t pc,pr;
            if((pc = fork()) == 1)
            {
                    printf("failed to create a new process
    ");
                    exit(0);
            }
            else if(pc == 0)/*如果是子进程*/
            {
                    sleep(10);/*睡眠10秒*/
                    exit(0);
            }
            do{/*如果是父进程*/
                    pr = waitpid(pc,NULL,WNOHANG);/*使用了WNOHANG参数,waitpid不会在这里等待*/
                    if(pr = 0)
                    {/*如果没有收集到子进程*/
                            printf("No child exited
    ");
                            sleep(1);
                    }while(pr == 0);/*没有收集到子进程,就继续尝试*/
            if(pr == pc)
            {
                    printf("successfully get child %d
    ",pr);
            }
            else
            {
                    printf("some error occured
    ");
            }
            return 0;
              }
    }
                                                                                                                 	
    
    运行结果:
    hyx@hyx-virtual-machine:~/test$ ./wait_example
    this is child process with pid of 5879
    (等待10秒)
    I catched a child process with pid of 5879
  • 相关阅读:
    P4387 P4387 【深基15.习9】验证栈序列
    P1241 括号序列题解
    P2058 海港题解
    P1540 机器翻译题解
    leaflet + react + typescript
    TypeScript中文手册:从 JavaScript 迁移到 TypeScript
    react-esri-leaflet与typescript
    TypeError: Super expression must either be null or a function
    前端库(gis前端库和普通库分开)
    react-leaflet:Module parse failed: Unexpected token (10:41)
  • 原文地址:https://www.cnblogs.com/myidea/p/4997131.html
Copyright © 2020-2023  润新知