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
。どんな助けやヒントもありがとう。