私はこの疑似コードを持っており、親に送信された信号が親が一時停止した後に実際に到着することを保証するために何を変更する必要があるのか疑問に思います。
int main()
{
int pid;
for(int i = 0; i < 5; i++)
{
if((pid = fork()) == 0)
{
mapp(i);
}
}
for(int i = 0; i < 5; i++)
{
/*Parent opens fifo i for reading*/
pause(); /*Parent must stop it's execution until child i writes to fifo i*/
/*Parent reads from the fifo number i => SUCCESS*/
}
}
void mapp(int i)
{
/*Children opens fifo i for writing*/
/*Children writes to fifo i*/
kill(getppid(), SIGCONT); /*Children notifies it's father so that he's now be able to read*/
}
論理的に問題はないようですね?しかし、残念ながら、プログラムは常に期待どおりに実行されるわけではありません。時々(常にそうではありませんが)、親プロセスが一時停止する前に信号が送信されるため、実行が中断され、親プロセスが一時停止されてもプログラムは中断されません。他のタイプの信号はすべて受信されます。
PD:sleep()
オプションではありません。プログラムの実行時間を延長できません。
ありがとうございます!
答え1
あなたは正しいです。あなたのプログラムは競争条件の影響を受けます。
ここで解決策は、各プロセスで通信パイプを作成して接続するのではなく、親プロセスで通信パイプを作成することです。 fifoを使用すると言われましたが、fifoファイルはパイプに似ていてファミリーなので、おそらくfifoが不要でパイプで十分です。
おおよその:
#define CHILDREN 5
int main()
{
int pid;
int pipes[CHILDREN][2];
for(int i = 0; i < CHILDREN; i++)
{
if (pipe(pipes[i]) == -1) {
// Error
]
pid = fork();
if(pid == -1) {
// Error
} else if (pid == 0) {
// Child
close(pipes[i][0]);
mapp(i, pipes[i][1]);
} else {
// Parent
close(pipes[i][1]);
}
}
for(int i = 0; i < CHILDREN; i++)
{
/*Parent reads from the pipe number i => SUCCESS*/
read(pipes[i][0], ...); // Will block until children writes
}
}
void mapp(int i, int fd)
{
/*Children writes to its pipe */
write(fd, "hello Dad!\n", 11);
}
親プロセスはパイプからデータを読み取ることができるまでブロックされるため、完全に効率的です。読むことができるまでブロックしたい場合どのパイプの場合は、select、epollなどを使用してこれを行うこともできます。
パイプへの書き込みは、PIPE_BUF(Linuxでは4096バイト)より小さいと仮定してアトミックに作成されます。最近のLinuxでは、O_DIRECTを使用して「パケット」モードを使用できます。すべての子供たちはパイプを持っていましたが、それは不要に見えました。