C在sigsuspend`

时间:2018-02-07 21:39:39

标签: c process signals fork

我正在尝试创建一个程序,其中进程分叉,创建子进程以及父进程必须始终在子进程完成打印到屏幕之前完成打印,无论如何。我还希望使用信号而不是流水线来实现这一目标。

这与此处提出的问题类似:Explanation of sigsuspend needed

我知道kill(pid,signal);是向该pid发送信号并告诉它完成执行并终止。

问题是,当它执行时,孩子在暂停后不会打印。下面是代码:

int main(void){
 pid_t  pid;
 int    i;
 pid = fork();

 if(pid==0){
      sigset_t mask;
      sigemptyset(&mask);
      sigaddset(&mask,SIGUSR1);
      printf("This is the child Process id = %d \n",getpid());
      sigsuspend(&mask);
      printf("The child is now complete \n");

 }

 else{
      printf("This is the parentProcess id = %d \n",getpid());
      printf("The  parentProcess is complete\n");
      sleep(1);
      int j = kill(pid,SIGUSR1);
      if (j!=0)
      {
           perror(NULL);
      }
      exit(0);
 }
}

我已经设法通过在main之前使用全局变量int x = 0;和信号处理程序方法void handle1(int s){x = 1;}来完成我的任务(在子项之前打印父项)。在主要内容中我添加了signal(SIGUSR1,handle1);在孩子中我移除了所有sigset和sigsuspend行,而是在while(x==0){/*do_nothing*/}语句之前写了printf 1行。因此,当父进程执行kill(pid,SIGUSR1)时,子进程继承的信号处理程序也会被执行并设置x = 1。所以孩子现在离开了while循环并且可以打印它的声明。

但是我相信知道如何使用sigmask_tsigsuspend()完成此任务会很有帮助,但我无法以这种方式工作。

2 个答案:

答案 0 :(得分:1)

你有一些问题。

您的父进程应该等待孩子完成。这允许诊断(例如正确地等待孩子打印),但是否则是一个簿记任务,即使等待过程刚刚退出也是一个好习惯:

  printf("This is the parentProcess id = %d \n",getpid());
  printf("The  parentProcess is complete\n");
  sleep(1);
  int j = kill(pid,SIGUSR1);
  if (j!=0)
  {
       perror(NULL);
       exit(0);
  }
  waitpid(pid, NULL, 0);
  exit(0);

现在,您已将掩码中的SIGUSR1设置为sigsuspend(),这会导致信号被忽略。一旦父母等待,这一点就更明显了,因为父母将永远不会退出。因此,请删除设置SIGUSR1

的代码行

最后,SIGUSR1的默认处理程序只会导致进程退出,因此printf将无法打印。如果要打印,则应为SIGUSR1添加信号处理程序。它不需要做任何事情。

void h (int s) {}
...

      sigset_t mask;
      sigemptyset(&mask);
      //sigaddset(&mask,SIGUSR1);
      printf("This is the child Process id = %d \n",getpid());
      struct sigaction sa = { .sa_handler = h };
      sigaction(SIGUSR1, &sa, NULL);
      sigsuspend(&mask);
      printf("The child is now complete \n");

答案 1 :(得分:1)

您的代码中存在3个问题:

  1. SIGUSR1是您想要传递给孩子的信号。你不能使用sigaddset(&mask,SIGUSR1);,它与你的意图完全相反。

  2. 根据下面的POSIX标准sigsuspend(),您应该为SIGUSR1安装信号处理程序,以使sigsuspend()继续以下代码,因为SIGUSR1的默认行为}终止。

  3.   

    sigsuspend()函数必须用sigmask指向的信号集替换调用线程的当前信号掩码,然后挂起线程,直到传递一个信号,其动作是执行信号捕获功能或终止流程

    1. 如果你从父母那里收集孩子会更好,否则会有竞争条件。
    2. 以下代码可以使用:

      #include <signal.h>
      #include <unistd.h>
      #include <stdio.h>
      #include <stdlib.h>
      
      void handler(int sig) {}
      
      int main(void){
       pid_t  pid;
       int    i;
       pid = fork();
      
       signal(SIGUSR1, handler);
      
       if(pid==0){
            sigset_t mask;
            sigemptyset(&mask);
            //sigaddset(&mask,SIGUSR1);
            printf("This is the child Process id = %d \n",getpid());
            sigsuspend(&mask);
            printf("The child is now complete \n");
       }
      
       else{
            printf("This is the parentProcess id = %d \n",getpid());
            printf("The  parentProcess is complete\n");
            sleep(1);
            int j = kill(pid,SIGUSR1);
            if (j!=0)
            {
                 perror(NULL);
            }
            wait(NULL);
            exit(0);
       }
      }