2014-09-06 92 views
0

父進程分叉兩個子進程,分別代替SIGUSR1SIGUSR2信號。發送和處理帶子進程信號的問題C

父進程取代SIGINT信號,在捕獲它時分別發送SIGUSR1SIGUSR2給它的孩子。

時按Ctrl-C應該是預期的輸出:

Ctrl+C is pressed。 
received SIGUSR1 signal 
received SIGUSR2 signal 

但在按Ctrl-C我有

Ctrl+C is pressed。 

我不知道爲什麼sig_handler_1sig_handler_2不excuted 。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <signal.h> 
void fun_ctrl_c(int); 
void sig_handler_1(int); 
void sig_handler_2(int); 
pid_t pid1; 
pid_t pid2; 
int status; 

int main() { 
    pid1 = fork(); 
    if (pid1 == 0) { // child 1 
     // avoid to be killed 
     (void) signal(SIGINT, SIG_IGN); 
     // replace SIGUSR1 
     (void) signal(SIGUSR1, sig_handler_1); 
     raise(SIGSTOP); 
    } else { 
     pid2 = fork(); 
     if (pid2 == 0) { // child 2 
      // avoid to be killed 
      (void) signal(SIGINT, SIG_IGN); 
      // replace SIGUSR2 
      (void) signal(SIGUSR2, sig_handler_2); 
      raise(SIGSTOP); 
     } else { // parent 
      (void) signal(SIGINT, fun_ctrl_c); 
      waitpid(-1, &status, 0); 
     } 
    } 
    return 0; 
} 

void fun_ctrl_c(int) 
{ 
    printf("Ctrl+C is pressed。\n"); 
    kill(pid1 ,SIGUSR1); 
    kill(pid2 ,SIGUSR2); 
    (void) signal(SIGINT, SIG_DFL); 
} 

void sig_handler_1(int) 
{ 
    printf("received SIGUSR1 signal\n"); 
} 

void sig_handler_2(int) 
{ 
    printf("received SIGUSR2 signal\n"); 
} 
+1

使用'替換'不是通常的術語。你似乎在'處理'這些信號,或者'用不同的信號處理器來代替'。 – 2014-09-06 19:37:52

回答

1

你的問題是,你的子進程raise(SIGSTOP);,所以他們停止,並且不能在所有的信號作出反應。

將其替換爲pause(); - 代碼即可使用。

#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <unistd.h> 

void fun_ctrl_c(int); 
void sig_handler_1(int); 
void sig_handler_2(int); 

pid_t pid1; 
pid_t pid2; 

int main(void) 
{ 
    pid1 = fork(); 
    if (pid1 == 0) 
    { 
     (void) signal(SIGINT, SIG_IGN); 
     (void) signal(SIGUSR1, sig_handler_1); 
     pause(); 
     printf("PID %d exiting\n", (int)getpid()); 
    } 
    else if ((pid2 = fork()) == 0) 
     { 
      (void) signal(SIGINT, SIG_IGN); 
      (void) signal(SIGUSR2, sig_handler_2); 
      pause(); 
      printf("PID %d exiting\n", (int)getpid()); 
     } 
     else 
     { 
      (void) signal(SIGINT, fun_ctrl_c); 
      int status; 
      int pid; 
      printf("Interrupt me!\n"); 
      while ((pid = waitpid(-1, &status, 0)) != -1) 
       printf("Child %d exited with status 0x%.4X\n", pid, status); 
      printf("Parent %d exiting\n", (int)getpid()); 
     } 
    return 0; 
} 

void fun_ctrl_c(int signum) 
{ 
    printf("Ctrl+C is pressed。Received SIGINT (%d) signal\n", signum); 
    kill(pid1, SIGUSR1); 
    kill(pid2, SIGUSR2); 
    (void) signal(SIGINT, SIG_DFL); 
} 

void sig_handler_1(int signum) 
{ 
    printf("received SIGUSR1 (%d) signal\n", signum); 
} 

void sig_handler_2(int signum) 
{ 
    printf("received SIGUSR2 (%d) signal\n", signum); 
} 

採樣運行(我稱爲程序sigintusr12):

$ ./sigintusr12 
Interrupt me! 
^CCtrl+C is pressed。Received SIGINT (2) signal 
received SIGUSR2 (31) signal 
received SIGUSR1 (30) signal 
PID 31184 exiting 
PID 31183 exiting 
Child 31184 exited with status 0x0000 
Child 31183 exited with status 0x0000 
Parent 31182 exiting 
$ 

請注意,你不應該嚴格使用printf()(和許多其他功能,特別是那些可能需要分配內存)在信號處理程序中。在這裏它可以正常工作,但這不是一個好的做法。有關更多信息,請參閱How to avoid using printf() in a signal handler?