如何不使用waitpid阻止父母

Posted

技术标签:

【中文标题】如何不使用waitpid阻止父母【英文标题】:how to not block parent with waitpid 【发布时间】:2014-04-08 14:03:11 【问题描述】:

我需要创建一个程序来创建 n 个进程并显示信息。当每个进程结束时,我要打印它的 PID 和退出状态。我这样做的方式是,父程序等待创建下一个进程,直到当前进程结束。我需要它,以便它继续创建子进程,并在一个进程结束时仅显示退出信息,而不会阻止父进程继续。我不知道在哪里等待以确保这一点。以下是我的代码:

int main (int argc, char *argv[])

  if (argc < 2)
  
     printf("\n\nUsage: %s <enter a number (12 or less)>\n\n", argv[0]);
     exit (-1);
  
  else
  
    int *processNum = (int *)malloc(sizeof(12));
    int processNumTemp;

    processNumTemp = atoi(argv[1]);
    processNum = &processNumTemp;

  if(*processNum > 12 || *processNum < 1)
    
      printf("\n\nUsage: %s <enter a number (12 or lrss)>\n\n", argv[0]);
    
  else
    
      parentInfo(processNum);
      createChildProcess(processNum);
    


  

 return 0;



//Name:  parentInfo
//Description:  Displays information about the parent process
//Parameters:  processNum - stores the number of child processes to create
//             (entered at the command line).
//Return:  none
void parentInfo(int *processNum)

 printf("Parent process ID:  %d\n", getppid());
 printf("Number of processes to create:  %d\n", *processNum);



//Name:  createChildProcess
//Description:  Creates n number of child processes.
//              For each child process, it says its a child process and it
//              displays its PID.
//              After each child process closes, the parent displays info.
//Parameters:  processNum - stores the number of child processes to create
//             (entered at the command line).
//Return:  none
void createChildProcess(int *processNum)

 int i;
 int childStatus;
 pid_t childpid;

 /*The for loop will create n number of processes based on the value of            processNum.*/
 for(i = 1; i <= *processNum; i++)
 childpid = fork();

  //Executes if fork didn't work
  if(childpid < 0)
    
      perror("fork");
      exit(1);
    

  //Executes if the fork worked
  else if( childpid == 0)
    
      int pid = getpid();

      //Prints a message and the child processe's PID
      printf("\nHello I am a child process.\n");
      printf("My PID is %d. \n", getpid());

      for(int x = 1; x <= pid; x ++);

      exit(15);
    


      //Executes after the child process has ended
      //Checks the child process's exit status

      waitpid(childpid, &childStatus, WUNTRACED);
      printf("\nPID of the child process that was just created:  %d.\n", childpid);

      if(WIFEXITED(childStatus))
        
          printf("PID %d exited normally.  Exit number:  %d\n", childpid, WEXITSTATUS(childStatus));
        
      else if(WIFSTOPPED(childStatus))
        
          printf("PID %d was stopped by %d\n", childpid, WSTOPSIG(childStatus));
        
      else if(WIFSIGNALED(childStatus))
        
          printf("PID %d exited due to signal %d\n.", childpid, WTERMSIG(childStatus));
        
      else
        
          perror("waitpid");
        

【问题讨论】:

为 SIGCHLD 设置信号处理程序。在处理程序中调用wait 【参考方案1】:

fork 之前的代码

signal(SIGCHLD, childHandler);

在 childHandler 中输入您的 waitpid 代码。

void childHandler(int signum)


    pid_t childpid;
    int childstatus;

    while ((childpid = waitpid( -1, &childstatus, WNOHANG)) > 0)
    
        if (WIFEXITED(childStatus))
        
            printf("PID %d exited normally.  Exit number:  %d\n", childpid, WEXITSTATUS(childStatus));
        
        else
            if (WIFSTOPPED(childStatus))
            
                printf("PID %d was stopped by %d\n", childpid, WSTOPSIG(childStatus));
            
            else
                if (WIFSIGNALED(childStatus))
                
                    printf("PID %d exited due to signal %d\n.", childpid, WTERMSIG(childStatus));
                
                else
                
                    perror("waitpid");
                
        
    

您不应该在信号处理程序中使用像 printf 这样的异步不安全调用,因此请更改您的代码以将状态保存在全局或堆分配数组中 - 您知道要从 processNum 创建的大小 - 并在外部打印状态信息处理程序。

此外,按照目前的结构,您的父母可能会在收割所有孩子之前结束。为孩子添加一个计数器,以便您在父母退出之前等待所有孩子。

【讨论】:

【参考方案2】:

查看信号SIGCHLD。如果您已阻止它,则必须取消阻止它,或者可能会明确检查它。

【讨论】:

什么是孤僻的孩子? 查看 *** 帖子 Detached vs. Joinable POSIX threads。在这种情况下,唯一重要的是它们没有分离。 OP 正在创建进程而不是线程。这是无关紧要的。苹果和橙子。【参考方案3】:

wait 的目的是,嗯,等待,所以解决问题的方法是首先创建所有孩子,然后开始等待它们终止。 这是一个执行此操作的程序:

// fork
#include <unistd.h>

// wait
#include <sys/types.h>
#include <sys/wait.h>

// exit
#include <stdlib.h>

//printf
#include <stdio.h>

void child( int id)

  int seed= id;
  int x= rand_r( &seed) % 10;
  sleep( x);

  exit( x);


int main( int argc, char *argv[])

  const int n= 5;
  int i;

  printf( "creating %d children.\n", n);
  for ( i= 0; i < n; ++i) 
    pid_t pid= fork();
    if ( !pid)
      child( i); // does not return
    else
      printf( "child [0x%x] created.\n", pid);
  

  // all the children are created now
  // now we wait for them to terminate

  printf( "waiting for children to terminate.\n", n);
  for ( i= 0; i < n; ++i) 
    int result;
    pid_t pid= wait( &result);
    printf( "child [0x%x] terminated with result [%u].\n", pid, WEXITSTATUS( result));
  

  puts( "all children terminated.");

【讨论】:

以上是关于如何不使用waitpid阻止父母的主要内容,如果未能解决你的问题,请参考以下文章

waitpid函数的使用方式

waitpid 函数详解

wait,waitpid学习测试

wait,waitpid学习测试

即使进程终止,waitpid 总是返回 -1

linux wait 和waitpid