c - 从父进程到子进程的管道无法正常工作

标签 c process pipe fork

对于我的作业,我需要创建一个包含四个选项(添加节点、列出节点、删除节点和退出)的菜单,并且当用户选择这四个选项之一(具有 1、2、3 或4),子进程处理选择。我还没有实现选项 2 或 3,所以不用担心这两个。这是我的代码,以便您了解布局:

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

int main()
{
    int p[2];
    char option[10];
    int node_num = 1;
    int rd, wr, tail = 0;

    pid_t first_fork;
    first_fork = fork();

    pipe(p);

    if (first_fork > 0)
    {
        // root
        do
        {
            printf("NODES MENU\n");
            printf("    1) ADD NODE\n");
            printf("    2) LIST NODES\n");
            printf("    3) REMOVE NODE\n");
            printf("    4) QUIT\n");
            printf("SELECT AN OPTION: ");

            fgets(option, 10, stdin);
            write(p[1], option, 1);

            if (option[0] != '1' && option[0] != '2' && option[0] != '3' && option[0] != '4')
            {
                printf("[Invalid Selection]\n");
            }
        } while (option[0] != '4');
    }
    else
    {
        // first node
        read(p[0], option, 1);

        if (option[0] == 1 && tail == 1)
        {
            int p2[2];
            node_num++;
            pipe(p2);
            pid_t cpid;
            cpid = fork();

            if (cpid > 0)
            {
                // parent
                tail = 0;
                wr = p2[1];
            }
            else
            {
                // child
                printf("[Node:  %d PID:     %d  HAS BEEN ADDED...]\n", node_num, getpid());
                tail = 1;
                rd = p2[0];
            }
        }
        if (option[0] == '2')
        {
            int i;
            for (i = 0; i < node_num; i++)
            {
                printf("[Node: %d   PID: %d     PPID: %d    RD: %d  WR: %d\n", node_num, getpid(), getppid(), rd, wr);
            }
        }
        if (option[0] == '3')
        {
            printf("remove");
        }
    }
}

到目前为止,我主要关心的是让添加选项正常工作。在使用 fgets 函数获取用户选项之后,父进程应使用 write()read() 写入第一个“节点”(子进程) 。然后,在子进程内部,应相应地处理选项(选项 4 除外,该选项由 do-while 循环处理)。

菜单运行完美;无效选择部分有效,选项 4 退出也有效。但是,当我选择选项 1 时,不会打印任何内容,并且菜单会再次弹出(就像预期的那样,直到我选择选项 4)。选项 2 和 3 也会出现同样的问题。

这是相同的输出:

NODES MENU
    1) ADD NODE
    2) LIST NODES
    3) REMOVE NODE
    4) QUIT
SELECT AN OPTION: 1
NODES MENU
    1) ADD NODE
    2) LIST NODES
    3) REMOVE NODE
    4) QUIT
SELECT AN OPTION: 4

子进程没有像预期那样打印任何内容。

我尝试将第一个子项的 else 更改为另一个 if 语句的形式

if (first_fork == 0)

但什么也没发生。事实上,我昨天尝试了同样的事情,我至少能够打印出节点已添加;但现在没有打印任何内容,我不知道我之前做了什么更改才能使其正常工作,但现在不行。

我尝试使用 close() 函数通过关闭子级中的 p[1](在 read() 之前)将数据从父级发送到子级)并在父级中关闭 p[0] (在 write() 之前)。这没有任何作用。

我想也许在我写给 child 之后我需要使用 wait(NULL) 函数调用,但这阻止了菜单弹出(也许我只是使用 wait 函数错误?)。

我尝试摆脱 && tail == 1 检查;那也没有做任何事情。

所以我剩下的唯一猜测是它与 do-while 循环有关,和/或管道未正确写入和读取,和/或 if 语句未正确读取字符有关。

最佳答案

你最大的两个错误是:

  • 您在创建管道之前进行了 fork 。

    这意味着父级和子级无法通信,因为它们都有自己的管道,而不是共享管道。您应该在 fork 之前创建一个管道。

  • 子进程没有循环。

    child 只从管道中读取一次。它应该循环地从管道中读取数据,直到它从父级收到终止自身的消息。

关于c - 从父进程到子进程的管道无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48935662/

相关文章:

c - 在结构中的函数中传递枚举(在 C 中)

arrays - 如何用C实现埃拉托色尼筛法算法?

java - 向进程发送 KeyEvents

java - 执行显示控制台窗口的命令并获取进程的句柄

C管道多条消息只收到一条

c - 在 AIX 上构建和打包的最佳实践

C - 使用 {} 进行视觉上高效的指针数组初始化

c# - 如何获得进程所有者的用户名?

linux - 子管道进程如何根据向父级发出的信号表现?

c管道为什么是fd[0]和fd[1] 3和4