簡體   English   中英

C 無法在`sigsuspend`后向子進程發出信號以繼續

[英]C Can't signal a child process to continue after `sigsuspend`

我正在嘗試創建一個程序,其中一個進程分叉,創建一個子進程,並且父進程必須始終在子進程完成打印到屏幕之前完成打印到屏幕,無論如何。 我也希望使用信號而不是流水線來實現這一點。

這是一個與這里提出的問題類似的問題: 需要 sigsuspend 的解釋

我明白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);
 }
}

我設法通過使用全局變量int x = 0;完成了我的任務(在孩子之前打印父母) int x = 0; 和信號處理方法void handle1(int s){x = 1;}在 main 之前。 在主要我添加了signal(SIGUSR1,handle1); 在孩子中,我刪除了所有 sigset 和 sigsuspend 行,而是在printf語句之前寫了while(x==0){/*do_nothing*/} 1 行。 因此,當父進程執行kill(pid,SIGUSR1) ,子進程繼承的信號處理程序也會被執行並設置 x=1。 所以孩子現在離開while循環並可以打印它的語句。

但是我相信知道如何使用sigmask_tsigsuspend()完成這項任務會很有幫助,但我無法讓它以這種方式工作。

你有幾個問題。

您的父進程應該等待子進程完成。 這允許診斷(例如正確等待孩子打印),但在其他方面是一個簿記任務,即使等待進程將退出,也是一個好習慣:

  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");

您的代碼中有 3 個問題:

  1. SIGUSR1是你想傳遞給孩子的信號。 你不能使用sigaddset(&mask,SIGUSR1); ,它與您的意圖完全相反。

  2. 根據下面的 POSIX 標准sigsuspend() ,您應該為SIGUSR1安裝一個信號處理程序,以使sigsuspend()繼續以下代碼,因為SIGUSR1的默認行為是終止。

sigsuspend() 函數應該用 sigmask 指向的一組信號替換調用線程的當前信號掩碼,然后掛起線程直到傳遞一個信號該信號的動作是執行信號捕獲函數或終止進程.

  1. 如果你從父母那里收集孩子會更好,否則會有競爭條件。

下面的代碼將起作用:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM