对于我的作业,我需要制作一个包含四个选项的菜单(添加节点,列表节点,删除节点和退出)以及当用户选择这四个选项之一时(使用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语句没有正确读取字符。
答案 0 :(得分:0)
你最大的两个错误是:
您在创建管道之前进行了分叉。
这意味着父和子无法通信,因为他们拥有自己的管道而不是共享管道。你应该在分叉之前创建一个管道。
子进程没有循环。
孩子只从管道读一次。它应该是从循环中的管道中读取,直到它从父级获取消息来自杀。