从父父到子进程的管道不起作用

时间:2018-02-22 19:25:22

标签: 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()之前)。这没有任何作用。

我想也许我在给孩子写信后需要使用wait(NULL)函数调用,但这会阻止菜单重新弹出(也许我只是使用wait函数错了? )。

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

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

1 个答案:

答案 0 :(得分:0)

你最大的两个错误是:

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

    这意味着父和子无法通信,因为他们拥有自己的管道而不是共享管道。你应该在分叉之前创建一个管道。

  • 子进程没有循环。

    孩子只从管道读一次。它应该是从循环中的管道中读取,直到它从父级获取消息来自杀。