我正在爲一個父級播放連接N個子進程的作業編寫一個程序。該程序使用管道在進程之間傳遞遊戲移動。用fork()和pipe()調用競爭條件
但是,我遇到了修復存在於我的程序中的競爭條件的問題。在遊戲結束後,子進程會掛起一個read()調用。這隻有在有多個子進程時纔會發生。
我已經嘗試了幾個東西,比如命名的信號燈,但我對叉子,管道和IPC還是很新的東西。我已與相關的代碼要點(我試圖把它清理乾淨是最好的,我可以爲可讀性)位置:
任何幫助,將不勝感激
編輯
以下是添加了聲明的要點的相關來源。
int main (int argc, char const *argv[])
{
int dimension = 8, children = 2, i;
int child_play_to_win = 0;
int fd[children][4];
pid_t childpid[children];
Board** boards = (Board**) malloc(sizeof(Board*) * children);
GameMove* lastMove, *tmpMove;
char buf[80];
for(i = 0; i < children; i++) {
generate_board(&(boards[i]), dimension);
int tmp[2];
pipe(tmp);
// child read
fd[i][0] = dup(tmp[0]);
// parent write
fd[i][1] = dup(tmp[1]);
pipe(tmp);
// parent read
fd[i][2] = dup(tmp[0]);
// child write
fd[i][3] = dup(tmp[1]);
childpid[i] = fork();
if(childpid[i] == -1) {
perror("fork");
exit(1);
}
if(childpid[i] == 0) {
srand(getpid());
close(fd[i][1]);
close(fd[i][2]);
while(!boards[i]->finished) {
// Read in move from parent
printf("child[%d] about to read\n", getpid());
read(fd[i][0], &buf, sizeof(GameMove));
// repeat parent move on this board
if(gameNotFinished) {
// make child move
// write move back to parent
write(fd[i][3], lastMove, sizeof(GameMove));
// If the board is finished (there was a win),
if (!gameNotFinihsed) {
// Child wins
close(fd[i][0]);
close(fd[i][3]);
printf("child[%d] ending\n", getpid());
break;
}
}
else {
// Parent won
close(fd[i][0]);
close(fd[i][3]);
break;
}
}
dealloc(boards[i]);
exit(0);
}
}
// When this hits children amount, all games are done
int games_complete = 0;
// Make first move to all children
for (i = 0; i < children; i++) {
close(fd[i][0]);
close(fd[i][3]);
lastMove = placePieceAtBestPosition(boards[i], 1);
printf("parent writing to child[%d]\n", childpid[i]);
write(fd[i][1], lastMove, sizeof(GameMove));
}
while (games_complete != children) {
for (i = 0; i < children; i++) {
// Read move from child
read(fd[i][2], &buf, sizeof(GameMove));
// repeat child move
// Check for a child win...
if (!checkForWin(boards[i], 2)) {
// No win yet, place piece at best position
lastMove = placePieceAtBestPosition(boards[i], 1);
// check for win again
boards[i]->finished = checkForWin(boards[i], 1);
// Write move back to child
write(fd[i][1], lastMove, sizeof(GameMove));
// If we won, close everything up and increment
// the games_complete counter.
if(boards[i]->finished) {
close(fd[i][1]);
close(fd[i][2]);
games_complete++;
}
} else {
// write back child move if there was a win
write(fd[i][1], lastMove, sizeof(GameMove));
close(fd[i][1]);
close(fd[i][2]);
printf("Parent lost!):\n");
games_complete++;
}
}
}
請發表(相關部分)代碼直接在你的問題,而不是通過鏈接。謝謝。 – 2013-03-06 18:17:48
打到我的第一件事就是你在創建管道後不需要這些'dup'調用。特別是因爲你不關閉原始文件描述符。根據您製作的子進程數量的不同,這可能會填滿文件描述符表。 – 2013-03-06 18:19:46
*爲什麼*你會鏈接100多行代碼,並且*不包括源文件頂部的開啓函數聲明? – WhozCraig 2013-03-06 18:19:57