2017-10-14 13 views
2

CMUの過去の試験でこの問題が見つかりましたが、どのように出力が可能かわかりません。子と親の信号の同時実行競合

基本的には、ユーザー定義のシグナルをブロックする親プロセスがあり、親プロセスが子プロセスをフォークするというアイデアです。最初に実行されるプロセス(別名:レースに勝つ)に基づいて、異なる出力が可能です。 Here is the question that is being asked in the exam

を(それを読んでください)と、ここでの試験からのコードです:

kill(pid,USRSIG1); 

int i = 1; 
void handler (int sig) { 
    i++; 
} 
int main() { 
    pid_t pid; 
    sigset_t s; 
    sigemptyset(&s); 
    sigaddset(&s, SIGUSR1); 
    signal(SIGUSR1, handler); 
    sigprocmask(SIG_BLOCK, &s, 0); 
    pid = fork(); 
     <LINE A> 
    if (pid != 0) { 
     i = 2; 
     <LINE B> 
    } else { 
     i = 3; 
     <LINE C> 
    } 
    sigprocmask(SIG_UNBLOCK, &s, 0); 
    pause(); /* pause to allow all signals to arrive */ 
    printf("%d\n", i); 
    exit(0); 
} 

我々は機能を配置する必要がありますので、テストする必要があり3例があります。 LINE AまたはLINE BまたはLINE Cのいずれかで、可能な出力を探します。

が今ここに私がやったことですが、私は

それそして、そこに信号SIGSUR1を追加し、その後、親が空集合Sを作成します、我々はプログラムを実行するとしましょうLINE Aに機能を配置しましたSIGUSR1シグナル用のカスタムハンドラを割り当て、セット内のシグナルをブロックします。これらの行であるかを

sigset_t s; 
    sigemptyset(&s); 
    sigaddset(&s, SIGUSR1); 
    signal(SIGUSR1, handler); 
    sigprocmask(SIG_BLOCK, &s, 0); 

はその後、親プロセスから新しい子が作成されますライン

pid = fork(); 

を実行します。

出力を決定するケースが2つあります。オペレーティングシステムは、親または子が最初に実行するようにスケジューリングします。

親が最初に実行されるとします。それから、LINE A(kill関数)を実行します。

そしてそれは親であるため、pid値は子のプロセスIDになります。 USRSIG1を子に送りますが、ブロックされているので何もしません。

ifステートメントは、グローバル変数iに値を割り当てます。プロセスが他の親その後、I = 2、であるならば、私は= 3だから私たちの親プロセスでは、我々は次の行が親に実行され、それがブロック解除されますI = 2

if (pid != 0) { //if i am a parent then i = 2 
     i = 2; 
     <LINE B> 
    } else { //if i am a child then i = 3 
     i = 3; 
     <LINE C> 
    } 

を持っていますそれは

は今、子供が実行される信号を受信するまでSIGUSR1信号 sigprocmask(SIG_UNBLOCK, &s, 0); と親プロセスは一時停止し、それは自分自身を含むプロセスグループ内のすべてのプロセスに終了(0、SIGUSR1)信号を送信します。しかし、それは子供の中でブロックされているので何も起こりません。親は信号を受信し、それは1ずつ増加します(したがって、親ではi = 3)。そして、関数の一時停止からI(3)の値を出力し、終了すると、親(親)が再開されます。

子がkill関数から再開し、それが子であるため、if文は真ではありません(したがって、子のiの値は3です)。子は、セットからの信号をブロック解除し、一時停止()します。

子に信号を送る他のプロセスがないので、それは永遠に一時停止したままであり、出力は親によってのみ3であった。そして、私たちが別の方法(子供が親の前で走る)に行くと、出力は4だけになります。

試験のソリューションでは、1回の実行で2つの出力があると私は混乱します。私はプロセスの1つがpause()にとどまっているので、これはどのように可能かは分かりません。

ソリューションのキーはLINE Aのための可能な出力であることを言う:私は質問から理解できることすべてである

3 4, 4 3, 3 5, or 5 3 

。どんな助けやヒントもありがとう。

答えて

0

子が最初に実行された場合、出力は自身と親の両方からの信号を受信するため、出力は5になります。両方のプロセスがのいずれかが完了する前に完了すると、pause()が終了したり、印刷されたりしません。

POSIXも終了しiタイプvolatile sig_atomic_tではないような任意のint値を印刷する子供とのための(ネットワークメッセージの代わりに、共有メモリを使用した場合など)により遅延された信号に印刷する両方のプロセスを可能にします。

質問者は、pause()が、送信された信号またはプロセスに送信される信号が受信されるまで、間違っていると誤解しているようです。

sigsuspendへの適切な呼び出しで置き換えられた場合、それは試験の著者の状態として機能します。親からの信号が遅すぎるか、それ自体からの信号と結合される可能性があるため、親は1つの信号を受信し、子は1つまたは2つの信号を受信します。

関連する問題