gpt4 book ai didi

c - fork() 和 pipeline() 的竞争条件

转载 作者:行者123 更新时间:2023-11-30 17:54:03 26 4
gpt4 key购买 nike

我正在为一项作业编写一个程序,其中父进程将四个子进程与 N 个子进程进行连接。该程序使用管道在进程之间传递游戏 Action 。

但是,我在修复程序中存在的竞争条件时遇到问题。有一种情况是子进程在游戏结束后挂起其 read() 调用。似乎只有当有多个子进程时才会发生这种情况。

我已经尝试过一些东西,例如命名信号量,但我对 fork 、管道和 IPC 仍然很陌生。我在这里发布了包含相关代码的要点(我尝试尽可能地清理它以提高可读性):

<强> Gist with relevant code

任何帮助将不胜感激

编辑

这是要点中的相关来源,并添加了声明。

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++;
}
}
}

最佳答案

我想我知道你的问题是什么。当您 fork 每个子项时,您将关闭其管道的父项。然而,每个 child 仍然为所有先前的 child 打开管道的父端。因此,只有最后创建的子级才会关闭其管道的父级端。

建议你改变:

close(fd[i][1]);
close(fd[i][2]);

类似:

for (j = 0; j <=i; j++) {
close(fd[j][1]);
close(fd[j][2]);
}

关于c - fork() 和 pipeline() 的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15254909/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com