对于有多个孩子的单亲,正确使用 fork() 和 pipeline() 。我该如何正确地做到这一点?

2024-04-20

So, my 上一篇文章 https://stackoverflow.com/questions/26321100/concept-any-good-c-example-of-fork-pipe-where-one-parent-creates-multiple被标记为偏离主题、过于模糊,并寻求有用代码的意见和建议。它做了这些事情,所以我重新发布作为我正在处理的代码的问题。感谢上一篇文章中的那些人,我能够通过回顾你们所说的内容来拼凑出我所拥有的内容。

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

该项目是一个 POSIX 纸牌游戏,其中父级(发牌者)使用父级自己的管道将其分叉为 5 个子级(玩家)。家长向玩家发牌(每人至少 5 张牌),直到一名玩家拿到 3 张相同的牌(不弃牌)。获胜的孩子将获胜的手牌和 EOF (exit(0)) 发送给父母以宣布胜利。这会触发父级打印获胜玩家并将 EOF 传输给剩余的子级以将其关闭(exit(1))。然后父级关闭。如果父级到达牌堆末尾而没有获胜者,则会将 EOF 传输给子级,等待它们退出 (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 才会发生。因此,您必须小心关闭所有进程中所有不需要的句柄。

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

  • 首先为子 0 创建两个管道
  • 然后分叉孩子0
  • child 0 关闭这些管道的父端,而parent 关闭这些管道的子端(好)
  • loop
  • 为孩子 1 创建两个管道
  • 叉子1
  • 子节点 1 关闭其管道的父端,而父节点关闭子端。

此时,您遇到了一个问题 - 子级 1 已将管道的父端继承到子级 0,但并未关闭它们。这意味着子进程 0 在从父进程读取时将无法检测到 EOF。同样的情况也发生在孩子 2 及之后的孩子身上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对于有多个孩子的单亲,正确使用 fork() 和 pipeline() 。我该如何正确地做到这一点? 的相关文章

随机推荐

  • 如何在 emacs 中对多种语言进行拼写检查?

    我主要使用 HTML 编写文档emacs作为我的主要编辑 Emacs 允许您使用以下命令以交互方式对当前缓冲区进行拼写检查ispell buffer 由于我在多种语言之间切换 因此我在文件末尾有一个 HTML 注释 指定该文件的主词典和个人
  • Github 贡献日历日开始时间

    几天前 Github 推出了他们的新功能 贡献 https github com blog 1360 introducing contributions 我有一个疑问 这个日历的一天开始时间是几点 是使用我的本地时间还是 UTC 如果它使用
  • C语言中如何将负零转换为正零?

    你好 我正在学习 Objective C 我正在做经典的计算器示例 问题是 当我将零乘以任何负数时 我得到负零 并将结果放入 双 类型 为了看看发生了什么 我使用了调试器 这就是我得到的结果 gdb 打印 2 0 1 0 gdb 打印 双精
  • Jquery 搜索 - 不区分大小写

    我在 Jquery 脚本上获得了一些帮助 该脚本创建了可搜索 可切换的常见问题解答 代码可以在这里看到 http jsfiddle net pT6dB 62 http jsfiddle net pT6dB 62 问题是 如果单词 How 带
  • JBoss AS 6 中的 QuartzScheduler 注入

    如何将 QuartzScheduler 服务注入 JBoss AS 6 上的无状态 bean 中 Quartz 服务在 JBoss AS 6 启动期间启动 00 58 38 025 INFO QuartzScheduler Schedule
  • Glassfish 4 中的密码加密算法

    我最近将 Glassfish 从 3 1 2 更新到 4 0 并希望设置一个我之前在我的应用程序上使用过的 JDBCRealm 该应用程序使用基于 FORM 的身份验证 密码在数据库中使用 SHA 256 进行哈希处理 这是默认的摘要算法选
  • 查找目录中最新的文件而不读取其所有内容

    我试图在一个巨大的文件系统中找出最新的文件 一种方法是浏览所有目录 一次一个 读取其内容 选择最新文件等 明显的缺点是我必须得到all特定目录中的文件 我想知道 Python 1 中是否有一个 Unix 支持的 神奇 调用来获取目录中的最新
  • Lua中如何获取目录列表

    我需要 LUA 中的目录列表 假设我的目录路径为 C Program Files 我需要该特定路径中所有文件夹的列表以及如何搜索该列表中的任何特定文件夹 Example 需要路径 C Program Files 中所有文件夹的列表 以下是上
  • 如何使用 Ruby 在现有 PDF 上编辑或书写?

    我有几个 PDF 模板文件 其中包含复杂的内容和几个空白区域 区域 我需要能够在这些空白区域写入文本并将生成的 PDF 保存在文件夹中 我在谷歌上非常集中地搜索了这个问题的答案 但没有找到明确的答案 更好的解决方案之一是PDF 工具包 ht
  • 读取由其他线程上的 Interlocked 更新的 int

    这是重复 如何正确读取 Interlocked Increment ed int 字段 https stackoverflow com questions 6139699 how to correctly read an interlock
  • mysql 选择不同的字母,包括扩展拉丁字符

    原问题 表结构 CREATE TABLE texts letter VARCHAR 1 CHARACTER SET utf8 COLLATE utf8 general ci NOT NULL text VARCHAR 255 CHARACT
  • 创建具有特定键的对象数组,然后从对象中删除该键

    我使用 lodash 从特定键创建对象数组 然后从其对象中删除该给定键 我有这个 var cars itemID KUsw42xU S1qA y3TiI use this as key name Car One qtd 1 itemID K
  • 在 jQuery 中获取默认服务器时间?

    如何使用 jQuery 获取网络服务器时间 这是一种无需服务器端任何特定代码甚至有效路径即可工作的方法 try var date new Date ajax type HEAD url getResponseHeader Date catc
  • VIM:在窗口左侧显示 3 个字符边框

    Context 我正在使用 NERDTree 插件 让我烦恼的一件事是 NERDTree 本身和我的代码之间的视觉垂直边界 我发现阅读我的代码有点烦人 我当前的设置如下所示
  • Minix 与 Linux 相比如何学习操作系统设计?

    我想学习操作系统设计 我想知道在此过程中我是否应该解决 Minix 或 GNU Linux 问题 我喜欢书籍 所以我主要关注一本书 尽管视频资源 大概是录像讲座 也很受欢迎 我已经正式学习了 C 和 C 可以用它们编写中小型程序 我对数据结
  • Java 泛型和设计模式:不参数化对泛型类型的引用总是一件坏事?

    这个问题与我的上一个问题部分相关question https stackoverflow com questions 7300163 java generic programming with unknown generic type of
  • 将 IntelliJ IDEA 缓存/索引目录移动到 RAM

    我正在尝试移动caches and index从 IntelliJ IDEA 配置目录到 RAM 挂载点的目录 tmp使用符号链接 我已经添加 tmpfs tmp ramdisk tmpfs defaults size 1024M x gv
  • React 路由器将查询附加到 URL

    React 路由器似乎在我的路由末尾附加了一个查询 该应用程序由运行 Express 的节点服务器提供服务 我正在使用最新版本的反应路由器 1 0 0 rc1 例子 http localhost 8080 users k 8wsy62 两个
  • Mercurial:虚拟合并后分支特定的更改不断返回

    我有一个 Mercurial 存储库 有两个永久分支 默认分支和 UAT 每隔一段时间 我们就会将应用程序的新版本部署 升级 到 UAT 环境 并通过将稳定的默认提交合并到 UAT 分支来实现这一点 有时 UAT 分支中的错误会得到修复 并
  • 对于有多个孩子的单亲,正确使用 fork() 和 pipeline() 。我该如何正确地做到这一点?

    So my 上一篇文章 https stackoverflow com questions 26321100 concept any good c example of fork pipe where one parent creates