私は2つのプロセス間の同期問題を解決しなければならず、信号でそれをやらなければなりません。このプロセスでSIGUSR1が処理されないのはなぜですか?
2つのプロセスで一定量の作業を行い、もう一方のプロセスに信号を送る必要があります。これは無期限に起こります。私のコードで何が起こる
は次のとおりです。
私は停止しないされ、再び親プロセスにシグナルを送り、子プロセスにシグナルを送り、親プロセスへの信号を、送信します、もう行動する。
理想的には、親と子はお互いに無期限に信号を送る必要があります。
int main() {
parent_pid = getpid();
pid_t pid = fork();
if (pid < 0) {
syserr_quit("fork error");
} else if (pid == 0) {
signal(SIGUSR2, child_work);
while (1) {}
} else {
child_pid = pid;
signal(SIGUSR1, parent_work);
while (1) {}
}
}
void child_work (int signo) {
sleep(1); // fake child work
if (kill(parent_pid, SIGUSR1) < 0) syserr_quit("kill error");
// wait for parent signal
pause();
}
void parent_work (int signo) {
sleep(1); // fake parent work
if (kill(child_pid, SIGUSR2) < 0) syserr_quit("kill error");
// wait for child signal
pause();
}
はそれがコードの本当に少量だとすべてが私には所定の位置にあると思われるので、間違っているかを把握することはできません。
誰かが自分のマシンでスピンアップしたい場合は、コピー/ペースト後に動作するa full demoがあります。
更新:は、sigaction(3)の代わりに、信号の(2)
いくつかのコメントを1として、私は競合状態を避けるためにsigaction
の使用に訴えるとデモでsleep
を使用して停止
SA_NODEFER
フラグを設定する必要があります。
コードはまだ動作していませんが、この時間は信号の受信を停止する子のみです。
スニペットがsignal
が交換されるのを除いて、上記と同様である - コンソールから確認し、シグナル伝達を開始する
struct sigaction action;
action.sa_handler = parent/child_work;
action.sa_flags = SA_NODEFER;
sigaction(signo, &action, NULL);
フルコード
と - の両方倍信号を送信します(つまり、kill -SIGUSR1 <parentid>
)
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void parent_work(int signo);
void child_work(int signo);
void syserr_quit(char *msg);
pid_t parent_pid;
pid_t child_pid;
int main() {
parent_pid = getpid();
printf("parent pid: %d\n", parent_pid);
pid_t pid = fork();
if (pid < 0) {
syserr_quit("fork error");
} else if (pid == 0) {
struct sigaction action;
action.sa_handler = child_work;
action.sa_flags = SA_NODEFER;
sigaction(SIGUSR2, &action, NULL);
while (1) {}
} else {
child_pid = pid;
printf("child pid: %d\n", pid);
struct sigaction action;
action.sa_handler = parent_work;
action.sa_flags = SA_NODEFER;
sigaction(SIGUSR1, &action, NULL);
while (1) {}
}
}
void child_work (int signo) {
for (int i = 0; i < 100000000; ++i); // fake child work
// signal parent that a write is now possible
printf("send signal to %d\n", parent_pid); fflush(stdout);
if (kill(parent_pid, SIGUSR1) < 0) syserr_quit("kill error");
printf("signal sent\n"); fflush(stdout);
// wait for parent signal
pause();
}
void parent_work (int signo) {
for (int i = 0; i < 100000000; ++i); // fake child work
// signal child that a read is possible
printf("send signal to %d\n", child_pid); fflush(stdout);
if (kill(child_pid, SIGUSR2) < 0) syserr_quit("kill error");
printf("signal sent\n"); fflush(stdout);
// wait for child signal
pause();
}
void syserr_quit(char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
フィン
さてさて、私が正しくsigaction
マスクを初期化していないという理由だけで更新されたコードが機能しなかったと思われる男。それはsigemptyset
で完了しなければならず、あなたはなぜright hereを見つけることができます。
詳細はthe answerです。あなたのSIGUSR1
シグナルハンドラparent_work
が呼び出されると
提示したよう、あなたのコードはコンパイルされません。シグナルハンドラは宣言されていない変数を参照し、すべての関数は宣言されていない関数 'syserr_quit()'を呼び出します。これは[mcve]の良いスタートですが、まだそこにはありません。 –
@JohnBollingerそれを読ませてください。その間、私は質問の最後の行に60行の完全なデモを提供しました。 – doplumi
(あなたのコードはコンパイルされないので)あなたの問題に接続されているかどうかは不明ですが、Linuxの 'signal(2)'マニュアルページから引用してください: "* の使用を避けてください:代わりにsigaction(2)を使用してください。 http://man7.org/linux/man-pages/man2/signal.2.html – cdarke