私のプログラムでは、ユーザーの入力に応じて fork() を数回行います。
場合によっては、SIGCHLD を処理して、「Process # Finished」のように言いたいことがあります。ただし、それ以外の場合は、この信号を無視したいと思います。
これどうやってするの?
シグナル処理は、プロセスに対してグローバルに設定されます。一部の子が終了し、他の子が終了しない場合に SIGCHLD のような非同期シグナルをキャッチしたい場合、事前にいくつかの子を無視することを決定することはできません。
親で毎回シグナルを処理する必要があり、ハンドラーでそれを無視するかどうかを決定します。
少なくとも、ハンドラーは子 (siginfo_t 構造体の si_pid) で wait() を実行して、戻りコードを収集する必要があります。その時点で、プロセス ID を確認して、他に何をすべきかを決めることができます。印刷したくない場合は何も印刷する必要はありません。
シグナル SIGCHLD をキャッチしてから、関数を呼び出します。これを行うために使用したいsignal()( man signal)。以下の例child_died()では、シグナル SIGCHLD がキャッチされた後に呼び出されます (子プロセスはこの時点で停止しています)。条件付きで子から親に渡す必要がある情報がある場合はchild_died()、パイプ ( ) を使用する必要がありますman pipe。シグナルとパイプの例を次に示します。
#include <signal.h>
#include <strings.h>
#include <stdio.h>
#define MAX_SIZE 256
void child_died(int);
int fd[2];
int main()
{
int pid;
extern int fd[];
char *str;
pipe(fd);
signal(SIGCHLD, child_died);
if ((pid = fork()) < 0) {
// error
printf("Error\n");
} else if (pid == 0) {
// child
printf("In child process\n");
close(fd[0]);
str = strdup("Message from child process.\n");
write(fd[1], str, strlen(str) + 1);
} else {
// parent
wait();
printf("Now in parent\n");
}
return 0;
}
void child_died(int s)
{
char *str;
close(fd[1]);
read(fd[0], str, MAX_SIZE);
printf("%s", str);
}
sigchld.c として保存され、以下でコンパイルされます。gcc -Wall sigchld.c -o sigchld
int (子 pid など) またはその他のデータ型を子プロセスから親プロセスに渡したい場合は、それを文字列に変換して戻すか、別の方法を見つける必要があります。
SIGCHLD を無視したい場合は、私の例ではそのロジックを に入れchild_died()ます。シンプルなif. シグナルを無視するタイミングと、必要なものをいつ出力するかをどのように決定しているのかわかりません。そのため、上記のコードにパイプを含めました。子プロセスからの情報を使用すると考えましchild_died()たが、親プロセスで呼び出されるため、子プロセスから親プロセスにデータを転送する方法が必要になります。
これが役立つことを願っています。私が知らない、これを達成するためのより良い、またはより簡単な方法があるかもしれません。もしあれば、コメントしてください。
waitpid関数をブロッキング モードまたは非ブロッキング モードのいずれかで使用して、特定の子からのシグナルを待ってから、何らかの処理を行うことができます。実際、グラハムの回答に記載されているように、何らかの方法で使用する必要があります...wait
SIGCHLD を無視すると、プロセス テーブルがゾンビでいっぱいになります。