2012-02-15 2 views
2

このプログラムの目的は、親ループが無限に割り込みを待つ間にフォークして子をスリープさせることです。^Cを押すと、void parent関数が呼び出されます。ただし、この部分は動作しますが、kill (pid, SIGALRM)のメッセージは機能しません。私はチェックし、pidは、その子供の正しいプロセスIDです。C++プロセスフォークとシグガラーム

私はしばらく検索しましたが、私が間違っていることは見つかりませんでした。私は親に子プロセスから前kill (pid, SIGALRM)を使用しますが、これは動作していない理由を私は理解することはできません。..

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

using namespace std; 

int pid; 

void parent (int sig) 
{ 
     kill (pid, SIGALRM); 
     cout << "I'm a parent " << getpid() << " My child is " << pid << endl; 
} 

void child (int sig) 
{ 
     cout << "I am " << getpid() << "my parent is " << getppid()<< endl; 
     cout << "Use ctrl+backslash to actually end the program" << endl; 
} 
int main() 
{ 
     pid = fork(); 
     if(pid == 0) 
     { //Child process 
       cout << "Child pid = " << getpid() << " Waiting for interrupt." << endl; 
       (void) signal (SIGALRM, child); 
       pause(); 
     } 
     else if(pid > 0) 
     { //Parent 
       sleep(2); 
       cout << "child pid = " << pid << endl; 
       struct sigaction act; 
       act.sa_handler = parent; 
       sigemptyset (&act.sa_mask); 
       sigaction (SIGINT, &act, 0); 
       while(1) 
       { 
         sleep (1); 
       } 
     } 
     return 0; 
} 
+1

出力は何ですか?また、どのOSでこれを実行していますか?また、ここではペナルティなので、これらのシグナルハンドラはCリンケージで定義する必要があります。 (つまり、それらをextern "C"ブロックに入れてください) – Arafangion

+0

また、iostreamがシグナルハンドラで使用するのが安全であることをどのように知っていますか?私はこれがhttp://stackoverflow.com/questions/7623401/override-ctrl-cの複製であるかどうか疑問に思っています(しかし、たとえそうであっても、この質問はそのままにしておく価値があると思います) – Arafangion

+0

私はFedora 15を使用しています。 私が手出力は次のようになります。 '子のpid = 23779 interrupt.' '子を待っているのpid = 23779' '^ CI'm親23778私の子供は23779' '^CI'm親であります23778私の子供は23779です。 '^ \終了(コアダンプ)' そして、extern Cブロックのおかげで、私はこれまでに使ったことがありません – OrangeGrover

答えて

0

[OK]を、ので、私はこの問題を考え出しました。
^ Cを押すと、メインプロセスの割り込みを受け取りますが、子プロセスを強制終了します。プログラムの中からsystem("ps")を実行したとき、それは子供のa.outプロセスが無効であることを示しました。 CHILD PRESERVER

struct sigaction act; 
act.sa_handler = CHILD_PRESERVER; 
sigemptyset (&act.sa_mask); 
sigaction (SIGINT, &act, 0); 

が生きてそれを維持除いて何もしなかったダミーの関数であった: は、この問題を解決するために、私は子供のプロセスに以下を追加しました。

この解決策は非常にエレガントであるとは思われません。だから、誰かがこれを行う正しい方法を持っている場合は、投稿してください。

0

あなただけsignal(SIGINT, SIG_IGN);

最初にあなたを倒してしまった(そして多くの場合、CTRL-Cとの信号を扱う新しいプログラマーをトリップ)のものを使用して、sigactionソリューションとして同じことを行うことができ、CTRL-Cが送信ということです1つのプロセスではなく、全体のプロセスグループへの信号 - グループ内のすべてのプロセスが信号を取得します。シグナルが送られるプロセスグループは、端末のフォアグラウンドプロセスグループです。

これで、Ctrl-C割り込みを扱う/制御する方法がたくさんあります。各プロセスには独自のSIGINTハンドラをインストールさせることができます。あるいは、プロセスグループを慎重に管理し、子プロセスグループ(通常はフォアグラウンドプロセスグループではない)に子プロセスを置くことができます。そのため、最初にシグナルを受け取ることはありません。

setpgrp(2)/ setpgid(2)システムコールを使用してプロセスグループを管理します。