gpt4 book ai didi

c - 正确的 fork() 和 pipe() 用于有多个 child 的单亲。我该怎么做?

转载 作者:太空狗 更新时间:2023-10-29 11:13:54 25 4
gpt4 key购买 nike

所以,我的 PREVIOUS POST被标记为偏离主题,过于模糊,并征求对有用代码的意见和建议。它做了那些事情,所以我重新发布了一个关于我正在处理的代码的问题。多亏了上一篇文章中的那些人,我才能够通过回顾你们所说的内容来拼凑我在这里的内容。

这里的重点是父子关系以及使用 fork() 和 pipe() 来获得所需的效果。

该项目是一个 POSIX 纸牌游戏,其中 parent (庄家)用他们自己的 pipe 从 parent 那里 fork 给 5 个 child (玩家)。 parent 向玩家发牌(每人至少 5 张牌),直到一名玩家有一张 3(没有弃牌)。获胜的 child 将获胜的手和 EOF(exit(0))发送给 parent 以宣布胜利。这会触发父进程打印获胜玩家并将 EOF 传输给其余的子进程以关闭它们(exit(1))。 parent 然后关闭。如果 parent 到达甲板的尽头但没有赢家,它会将 EOF 传输给 child ,等待他们退出(1)...然后关闭。

我的主要问题是子程序如何单独读取每张卡片,而不是一遍又一遍地从管道读取相同的值。我想我缺少一种同步父写入管道和子从管道读取的方法。

我对这些人完全陌生,所以非常感谢任何帮助。非常感谢。

代码更新:(编译有很多问题)完成并编译,但我显然在管道和通过它们中继数据方面遇到了问题。这里有很多错误,从无法玩游戏,到无法读取或写入管道,再到离开僵尸进程。我很感激任何关于我的烂摊子的意见。哈哈

这是我运行程序 (play.c) 时的输出:

os@debian:~/Documents/cpsc351/projects/assn2$ gcc -o play play.c
os@debian:~/Documents/cpsc351/projects/assn2$ ./play
Pipe Success...toChild 1 created.
Pipe Success...toParent 1 created.
Pipe Success...toChild 2 created.
Pipe Success...toParent 2 created.
Pipe Success...toChild 3 created.
Pipe Success...toParent 3 created.
Pipe Success...toChild 4 created.
Pipe Success...toParent 4 created.
Pipe Success...toChild 5 created.
Pipe Success...toParent 5 created.
Parent: All players are at the table. Dealing cards...
30 5C to player 1
51 KS to player 2
9 10H to player 3
25 KD to player 4
6 7H to player 5
18 6D to player 1
45 7S to player 2
29 4C to player 3
37 QC to player 4
12 KH to player 5
7 8H to player 1
19 7D to player 2
20 8D to player 3
49 JS to player 4
35 10C to player 5
15 3D to player 1
5 6H to player 2
36 JC to player 3
0 AH to player 4
22 10D to player 5
48 10S to player 1
27 2C to player 2
42 4S to player 3
16 4D to player 4
32 7C to player 5
4 5H to player 1
14 2D to player 2
41 3S to player 3
39 AS to player 4
1 2H to player 5
26 AC to player 1
46 8S to player 2
34 9C to player 3
11 QH to player 4
24 QD to player 5
17 5D to player 1
31 6C to player 2
44 6S to player 3
40 2S to player 4
3 4H to player 5
21 9D to player 1
50 QS to player 2
13 AD to player 3
33 8C to player 4
23 JD to player 5
43 5S to player 1
2 3H to player 2
28 3C to player 3
47 9S to player 4
38 KC to player 5
10 JH to player 1
8 9H to player 2
Child: Fork Success...Player 4 is sitting at the table.
Child: Player 4 is dealt a KD. Hand Total = 1 cards.
Child: Player 4 is dealt a QC. Hand Total = 2 cards.
Child: Player 4 is dealt a JS. Hand Total = 3 cards.
Child: Player 4 is dealt a AH. Hand Total = 4 cards.
Child: Player 4 is dealt a 4D. Hand Total = 5 cards.
Child: Player 4 is dealt a AS. Hand Total = 6 cards.
Child: Player 4 is dealt a QH. Hand Total = 7 cards.
Child: Player 4 is dealt a 2S. Hand Total = 8 cards.
Child: Player 4 is dealt a 8C. Hand Total = 9 cards.
Child: Player 4 is dealt a 9S. Hand Total = 10 cards.
Child: Fork Success...Player 5 is sitting at the table.
Child: Player 5 is dealt a 7H. Hand Total = 1 cards.
Child: Player 5 is dealt a KH. Hand Total = 2 cards.
Child: Player 5 is dealt a 10C. Hand Total = 3 cards.
Child: Player 5 is dealt a 10D. Hand Total = 4 cards.
Child: Player 5 is dealt a 7C. Hand Total = 5 cards.
Child: Player 5 is dealt a 2H. Hand Total = 6 cards.
Child: Player 5 is dealt a QD. Hand Total = 7 cards.
Child: Player 5 is dealt a 4H. Hand Total = 8 cards.
Child: Player 5 is dealt a JD. Hand Total = 9 cards.
Child: Player 5 is dealt a KC. Hand Total = 10 cards.
Child: Player 5 has left the table.
os@debian:~/Documents/cpsc351/projects/assn2$ Child: Player 4 has left the table.
Child: Fork Success...Player 3 is sitting at the table.
Child: Player 3 is dealt a 10H. Hand Total = 1 cards.
Child: Player 3 is dealt a 4C. Hand Total = 2 cards.
Child: Player 3 is dealt a 8D. Hand Total = 3 cards.
Child: Player 3 is dealt a JC. Hand Total = 4 cards.
Child: Player 3 is dealt a 4S. Hand Total = 5 cards.
Child: Player 3 is dealt a 3S. Hand Total = 6 cards.
Child: Player 3 is dealt a 9C. Hand Total = 7 cards.
Child: Player 3 is dealt a 6S. Hand Total = 8 cards.
Child: Player 3 is dealt a AD. Hand Total = 9 cards.
Child: Player 3 is dealt a 3C. Hand Total = 10 cards.
Child: Player 3 has left the table.
Child: Fork Success...Player 2 is sitting at the table.
Child: Player 2 is dealt a KS. Hand Total = 1 cards.
Child: Player 2 is dealt a 7S. Hand Total = 2 cards.
Child: Player 2 is dealt a 7D. Hand Total = 3 cards.
Child: Player 2 is dealt a 6H. Hand Total = 4 cards.
Child: Player 2 is dealt a 2C. Hand Total = 5 cards.
Child: Player 2 is dealt a 2D. Hand Total = 6 cards.
Child: Player 2 is dealt a 8S. Hand Total = 7 cards.
Child: Player 2 is dealt a 6C. Hand Total = 8 cards.
Child: Player 2 is dealt a QS. Hand Total = 9 cards.
Child: Player 2 is dealt a 3H. Hand Total = 10 cards.
Child: Player 2 is dealt a 9H. Hand Total = 11 cards.
Child: Player 2 has left the table.
Child: Fork Success...Player 1 is sitting at the table.
Child: Player 1 is dealt a 5C. Hand Total = 1 cards.
Child: Player 1 is dealt a 6D. Hand Total = 2 cards.
Child: Player 1 is dealt a 8H. Hand Total = 3 cards.
Child: Player 1 is dealt a 3D. Hand Total = 4 cards.
Child: Player 1 is dealt a 10S. Hand Total = 5 cards.
Child: Player 1 is dealt a 5H. Hand Total = 6 cards.
Child: Player 1 is dealt a AC. Hand Total = 7 cards.
Child: Player 1 is dealt a 5D. Hand Total = 8 cards.
Child: Player 1 has at least "3 of a Kind". Hand Total = 8 cards.

当前代码:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "cards.h"
#include "cards.c"

#define READ 0
#define WRITE 1

#define PLAYERS 5

int main(int argc, char *argv[])
{
//loop declarations ***Would not let me initialize within a for-loop...c99 error.***
int i;
int j;


pid_t player[PLAYERS];
int toChild_pipe[PLAYERS][2];
int toParent_pipe[PLAYERS][2];
int dealt_card;
int card_count = 1;
int player_count = 0;
int status_forChild;
int status_forParent;
int player_card;

for(i = 0; i < PLAYERS; i++)
{
// Create the pipes
if (pipe(toChild_pipe[i]) < 0)
{
perror("'To-Child' Pipe Error\n");
exit(1);
}

if (pipe(toParent_pipe[i]) < 0)
{
perror("'To-Parent' Pipe Error\n");
exit(1);
}

// Fork the child (new player)
player[i] = fork();
if (player[i] < 0)
{
perror("Fork Error:");
printf(" Player %d cloud not sit at table.\n", i+1);
exit(1);
}

else if (player[i] > 0) //Parent Process
{
// Close unsed pipe ends in Parent
close(toChild_pipe[i][READ]);
close(toParent_pipe[i][WRITE]);
}

else //(player[i] == 0)-- Child Process
{
int player_num = (i+1);
int player_card;
int hand[13] = {0};
int player_card_count = 0;
bool game_over = false;


printf("Child: Fork Success...Player %d is sitting at the table.\n", player_num);

// Close unsed pipe ends in Parent
close(toParent_pipe[i][READ]);
close(toChild_pipe[i][WRITE]);

while(!game_over)
{

if ((status_forChild = read(toChild_pipe[i][READ], &player_card, sizeof(player_card))) == 0)
{
//EOF from parent. Player lost.
game_over = true;
close(toParent_pipe[i][WRITE]);
close(toChild_pipe[i][READ]);
printf("Child: Player %d has left the table.\n", player_num);
exit(1);

}

else if (status_forChild == -1)
{
perror("");
printf("Child %d: ERROR: Could not read from pipe.\n", i+1);
exit(1);
}

else
{
//Players have 5 cards, loop through hand to check for winner. If yes, WIN.
if (player_card_count == 5)
{
for (j = 0; j < 13; j++)
{
if(hand[j] >=3)
{
//WINNER! Close process (status = 0)
printf("Child: Player %d has at least. Hand Total = %d cards.\n"
, player_num, rank(player_card));
close(toParent_pipe[i][WRITE]);
close(toChild_pipe[i][READ]);
exit(0);
}
}
}

//Read the current card value dealt, increment card value in hand array
int card_index = value_index(rank(player_card));
hand[card_index]++;
player_card_count++;


printf("Child: Player %d is dealt a %s%s. Hand Total = %d cards.\n", player_num, rank(player_card),
suit(player_card), player_card_count);

if ((hand[card_index] >= 3)&&(player_card_count > 5)) //at least (3 of a kind) and (> 5 card hand)
{
//WINNER! Close process (status = 0)
printf("Child: Player %d has at least. Hand Total = %d cards.\n", player_num, rank(player_card));
close(toParent_pipe[i][WRITE]);
close(toChild_pipe[i][READ]);
exit(0);
}
}
}
}
}

shuffle();
printf("Parent: All players are at the table. Dealing cards... \n");

while ((dealt_card = deal()) != EOF)
{

//Card is written to the pipe for current player
if ((status_forParent = write(toChild_pipe[i][WRITE], &dealt_card, sizeof(dealt_card))) == -1)
{
perror("");
printf("Parent: ERROR: Could not read from pipe for Child %d.\n", i+1);
exit(1);
}

//If child process exited with status = 0, child had 3 of a kind and wins game.
else if (status_forParent == 0)
{
printf("Parent: Player %d has WON!!!\n", player_count+1, rank(player_card));
break;
}

else
{

printf(" %d %s%s to player %d\n", dealt_card, rank(dealt_card), suit(dealt_card), player_count+1);

if (player_count >= PLAYERS-1)
player_count = 0;
else
player_count++;


}
}
// Close pipe ends
close(toParent_pipe[i][READ]);
close(toChild_pipe[i][WRITE]);
wait(NULL);
return 0;
}

最佳答案

您遇到的基本问题是您依赖 EOF 来检测事物,但是直到管道写入端的所有句柄都关闭后才会出现 EOF。因此,您必须小心关闭所有进程中所有不需要的句柄。

在您的代码中,您有一个循环创建管道,然后 fork :

  • 首先为 child 0 创建两个管道
  • 然后 fork child 0
  • 子 0 关闭这些管道的父端,而父关闭这些管道的子端(好)
  • 循环
  • 为 child 1 创建两个管道
  • fork 1
  • 子 1 关闭其管道的父端,而父关闭子端。

此时,您遇到了一个问题—— child 1 继承了到 child 0 的管道的父端,但没有关闭它们。这意味着 child 0 在从 parent 读取时将无法检测到 EOF。同样的事情发生在 child 2 和以后的 child 身上。

关于c - 正确的 fork() 和 pipe() 用于有多个 child 的单亲。我该怎么做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26331975/

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