簡體   English   中英

無法在C中向子進程發送信號

[英]Trouble sending signal to child process in C

我一直試圖弄清楚這是否可行,就像我做的那樣。 該程序應該派生一個循環打印到STDOUT的子進程,父進程應退出以返回終端提示符。 然后孩子應該等待SIGINT告訴它什么時候關閉。 但是我記得讀過SIGINT只發送到前台的進程,這解釋了為什么我的被遺棄的孩子不受CTRL + C的影響。 有沒有辦法讓被遺棄的孩子接收終端發送的信號,或者終端中的某些系統調用將它帶到可以接收SIGINT的前台? 或者我的搜索無望?

碼:

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

/* signal handler for the child process */
void catchInt (int signum)
{
 printf("\nMy sincerest apologies, master\n");
    exit(0);
}

/* signal handler for the parent process */
void ignoreInt (int signum)
{
 /* prevent any extra output from being printed */
 fflush(stdout); 
 /* wait for child to apologize before replying */
 wait(NULL);
 printf("You're welcome\n");
 exit(0);
}

/* signal handler for the child's alarm */
void catchAlarm (int signum)
{
 printf("It's great to be alive\n");
 /* reset the alarm */
 signal(SIGALRM, catchAlarm);
 alarm(3);
}

int main () {

 pid_t  pid;

 /* fork process */
 pid = fork();
 if (pid < 0) /* error handler */ 
 {   
  fprintf(stderr, "Fork Failed");
  exit(-1);
 }

 /* child */
 else if (pid == 0) 
 { 
  printf("It's great to be alive\n");
  /* catch SIGINT and handle as the child should */
  signal(SIGINT, catchInt);
  /* catch SIGALRM being sent by alarm() */
  signal(SIGALRM, catchAlarm);
  /* set alarm for 3 seconds */
  alarm(3);
  for ( ;; )
  {
   printf("I have 42001 children and not one comes to visit\n");
   usleep(500000);
  }   
 }

 /* parent */
 else 
 {
  /* exit to abandon child process in the background */
  exit(0);
 }

 return(0);
}

如果您希望您的孩子在控制終端上擊中中斷字符時接收SIGINT ,則它需要位於前台進程組中。 你可以實現這個目標:

int ctty = open("/dev/tty", O_RDONLY);
while (tcgetpgrp(ctty) == getpgrp())
    usleep(100000);
setpgid(0, tcgetpgrp(ctty));
close(ctty);

(你必須等到shell在你父命令退出后更改前台進程組時 - 我不確定有什么比在循環中旋轉更好的方法,如示例中所示。建議歡迎......)


PS:請注意,前台進程組可以隨時更改 - 例如,從shell運行另一個進程時。 我不確定你的最終目標是什么,但也許有更好的方法去做,不管它是什么。

您可以使用kill命令將信號發送到指定的進程號:

kill -2 12345

當然,如果您的代碼識別要殺死的PID(孩子在開始循環時應該報告其PID),它會有所幫助。 但是只需進行一些微小的更改(比如省略未使用的ignoreInt()函數,並報告子進程的PID),它就可以正常工作了 - 而kill命令也可以使用它。

壓縮代碼:

#include  <stdio.h>
#include  <unistd.h>
#include  <stdlib.h>
#include  <signal.h>

static void catchInt(int signum)
{
    printf("\nMy sincerest apologies, master (%d)\n", signum);
    exit(0);
}

static void catchAlarm(int signum)
{
    printf("It's great to be alive (%d)\n", signum);
    signal(SIGALRM, catchAlarm);
    alarm(3);
}

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

    if (pid < 0)
    {   
        fprintf(stderr, "Fork Failed");
        exit(-1);
    }
    else if (pid == 0) 
    { 
        printf("It's great to be alive (%d)\n", (int)getpid());
        signal(SIGINT, catchInt);
        signal(SIGALRM, catchAlarm);
        alarm(3);
        for ( ;; )
        {
            printf("I have 42001 children and not one comes to visit\n");
            usleep(500000);
        }   
    }
    return(0);
}

如果要包含<sys/types.h> ,它通常應該是POSIX頭中的第一個(因此在<unistd.h>之前)。 它最后列出的事實表明你根本不需要它 - 但我似乎記得你之前斷言你認為有必要的問題。 (OTOH,沒有調用任何wait()系列,所以<sys/wait.h>是不必要的,我有點確信大多數現代系統都不需要<sys/types.h> 。)

不, SIGINT信號僅在使用CTRL C (或設置了intr鍵擊的任何stty )操作發送到前台進程。

您始終可以使用kill -INT 99999 (其中99999是進程ID)將SIGINT發送到特定進程。

暫無
暫無

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

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