gpt4 book ai didi

c - 读取子进程中的管道卡在第二次读取上

转载 作者:行者123 更新时间:2023-11-30 14:54:24 26 4
gpt4 key购买 nike

我正在做一项作业,我必须创建一个链表,该链表由通过称为节点的管道进行通信的进程组成。该程序必须从根进程和名为 Node 1 的子进程开始。用户有四个选项,我被困在选项 1 上,用户应该能够添加节点(进程)。

根进程应该是唯一要求用户输入的进程。其余的应该循环,直到它到达读取 block 并等待写入。

当用户输入 1 时,程序检查当前进程是否是最后一个节点(在本例中为节点 1)。如果不是,该进程将通过在每个 fork 之前创建的管道将输入写入下一个节点。如果是,该进程将重置 isLast 变量并创建一个新的管道和 fork 。然后,子进程(节点 2)循环并陷入读取状态,父进程紧随其后。然后 Root 再次要求使用输入。

问题在于,程序似乎没有遇到任何问题,可以完成一次并创建节点 2,但第二次完成时,节点 1 挂起,即使根在“添加节点”中对其进行写入

非常感谢任何帮助!

#include <stdio.h>
#include <unistd.h>

int main(){
int isLast = 0;
int originPID = getpid();
int input = 0;
int node;
int p[2];

//Node 1
printf("%s\n", "Forking");
pipe(p);
int pid = fork();

//Set Node 1 to last
if(pid == 0){
isLast = 1;
node = 1;
}

while(input != 4){
//Node Read Block
if(getpid() != originPID){
printf("stuck\n");
read(p[0], &input, sizeof(input));
printf("free\n");
}

//MENU (Root Only)
if(getpid() == originPID){
sleep(1);
printf("%s", "User Options: Enter a number \n1. Add Node\n2. List Processes\n3. Remove Node\n4. Quit\n");
scanf("%d", &input);
}

//(1) Add Node
if(input == 1){
//Checks if last.
if(isLast == 1){
isLast = 0; //Reset isLast

//Create pipe and new process
printf("%s\n", "Forking");
pipe(p);
pid = fork();
if(pid == 0){
isLast = 1;
node++; //Label Node
}
}
//Write to next node
else{
write(p[1], &input, sizeof(input));
}
}
}
}

最佳答案

当最后一个节点从管道中读取 1 时,它必须创建一个新管道,通过该管道与即将创建的新节点进行通信。我想这就是它调用 pipe(p) 的原因。但这是一个问题,因为 p[0] 包含它读取其自己的输入的文件句柄的唯一副本。当它下次尝试读取输入时,它将尝试从为下一个节点设置的管道中读取数据——它实际上已经将自己与前一个节点断开了连接。

pipe() 在其中写入文件句柄的数组并没有什么神奇之处。句柄只是整数。那么,一个简单的解决方案是让子进程创建并使用从其父进程继承的读取文件描述符的副本,而不是引用存储在数组元素中的值。

此外,您应该确保在 fork 之后,父级和子级各自关闭自己不会使用的管道末端的副本。 (父级关闭读取端;子级关闭写入端。)您也许可以让程序在没有文件描述符的情况下工作,但至少会泄漏文件描述符。在某些情况下,打开文件描述符的额外副本可能会导致程序挂起。

关于c - 读取子进程中的管道卡在第二次读取上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46759292/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com