对于我的作业,我需要创建一个包含四个选项(添加节点、列出节点、删除节点和退出)的菜单,并且当用户选择这四个选项之一(具有 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/