2011-09-12 5 views
2

私は初心者C dev。私はCがどのように殺し、シグナルと睡眠を管理するのかを理解しようとしています。参照:何らかの理由で子プロセスに信号を送信できなくなりました。睡眠機能の変更結果が奇妙な方法で

void son1_handler(int sig) 
{ 
    printf("[SON1]:"); 
    fflush(stdout); 
} 

void son2_handler(int sig) 
{ 
    printf("[SON2]:"); 
    fflush(stdout); 
} 

int main(int argc, char **argv) 
{ 
    pid_t son1, son2; 
    son1 = fork(); 
    if (son1 == 0) 
    { 
     while (1) 
     { 
      signal(SIGUSR1, son1_handler); 
     }; 
    } 

    son2 = fork(); 
    if (son2 == 0) 
    { 
     while (1) 
     { 
      signal(SIGUSR2, son2_handler); 
     }; 
    } 

    while (1) 
    { 
     sleep(1); 
     kill(son1, SIGUSR1); 
     kill(son2, SIGUSR2); 
    } 
} 

私の目的は、印刷することです:[SON1]:[SON2]:[SON1]:[SON2] .... 上記のコードでは、時には[SON2]、ということだ:[SON1 ]:

kill(son1, SIGUSR1); 
sleep(1); 
kill(son2, SIGUSR2); 

が、驚くほどの結果は以下のとおりであった::[SON2] ...

私はキルの間に睡眠を使用して変更する考え[SON2]:[SON2]:[SON2]:[SON2]:[ SON2] ....

私は誤解しなければならないと思う睡眠、殺し、または信号に関する何かをg。あなたはなにか考えはありますか?本当にありがとうございます。

答えて

1

これは、プロセススケジューリングによるものです。

信号を送信すると、PCBの対応するビット(Process Control Block)が設定されます。 に送信され、信号が送信されたプロセスがスケジュールされると、シグナルがチェックされ、ハンドラが実行されます。

上記の例では、親プロセスが次々にシグナルを送信していますが、 'son1'が 'son2'の前に実行される保証はありません。

スリープでは、オペレーティングシステムが「コンテキストを切り替える」、つまり他のプログラムを実行できるようにするだけです。したがって、この場合

kill(son1, SIGUSR1); 
sleep(1); 
kill(son2, SIGUSR2); 

あなたは信号をson1に送信し、親プロセスをスリープ状態にします。ただし、親プロセスの前に再度son1プロセスをスケジュールする必要はありません。これは、オペレーティングシステムのプロセススケジューラによって異なります。前述のように同期を達成するには、セマフォーのような何らかのミューテックス・メカニズムを使用する必要があります。

問題を解決するための希望。

編集: また、Linuxでは、信号ハンドラは、1回の呼び出し後にシグナルハンドラが登録解除されるUnixとは異なり、その後の呼び出しの後でも登録されたままです。つまり、while()ループの各繰り返しを呼び出すのではなく、子プログラムでsignal()を一度呼び出すだけで済みます。

+0

ありがとうございます。今私にははるかに明確です。素晴らしい応答。 – juancancela

関連する問題