Process
向暫停的父程序發送信號並保證它會在父程序暫停後到達
我有這種虛擬碼,我想知道我必須改變什麼,以保證發送給父母的信號確實會在父母暫停之後到達。
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()
不是一個選項,我不能延長程序的執行時間。謝謝!
你是對的,你的程序受制於競爭條件。
這裡的解決方案是在父程序中創建通信管道,而不是讓每個程序創建並連接它們。您提到他們使用fifos,但是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 並擁有“數據包”模式。儘管由於您每個孩子都有一個管道,但這似乎是不必要的。