2010-09-23 61 views
5

我一直在試圖弄清楚,如果這是可能的方式,我已經做到了。這個程序應該分叉一個循環打印到STDOUT的子進程,父進程應該退出以返回終端提示符。然後,小孩應該等待SIGINT告訴它何時關機。但是我記得讀到SIGINT只發送給前臺進程,這就解釋了爲什麼我遺棄的孩子不受CTRL + C的影響。有沒有辦法讓被遺棄的孩子接收終端發送的信號,或者終端中的某些系統呼叫將其帶到可以接收到SIGINT的前臺?還是我的搜索無望?無法發送信號給子進程C

代碼:

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

回答

2

如果您希望您的孩子在控制終端上點擊中斷字符時收到SIGINT,它需要位於前臺進程組中。你可以做到這一點:

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

(你必須等待,直到外殼父退出後改變了前臺進程組,雖然 - 我不知道一個更好的辦法來做到這一點比在一個循環中打轉,如在本例中建議表示歡迎...)


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

+0

這實際上完美的作品!我將不得不更加關注進程組。謝謝! – JKomusin 2010-09-23 04:34:02

+0

@JKomusin:儘管這不是一個完全可靠的解決方案,但請參閱更新。 – caf 2010-09-23 04:45:15

1

可以使用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>不需要上最先進的系統。)

+0

哈哈,我幾乎積極的我的Ubuntu的上網本發行版是我的sys/types.h麻煩的來源,沒有它pid_t未申報我。但是在我的系統中還有其他這樣的頭文件丟失了,所以它並不令人震驚。過多的標題的原因是我相信我剛剛複製我的所有標題,當我做這個,並沒有修剪脂肪。儘管感謝你的迴應,殺死對我的目的atm足夠好。 – JKomusin 2010-09-23 04:24:23

0

沒有,SIGINT信號只發送到前臺當它通過使用CTRLC(或任何stty具有intr keystroke設置爲)來處理時,處理

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

+0

謝謝,kill -INT現在必須要做。 – JKomusin 2010-09-23 04:14:27