C 死锁linux管道
我想学习Linux管道是如何工作的!我编写了一个简单的小程序,它使用管道在父进程和子进程之间传递字符串。然而,这个程序导致了一个死锁,我不知道它的原因是什么 代码如下:C 死锁linux管道,c,linux,unix,linux-kernel,pipe,C,Linux,Unix,Linux Kernel,Pipe,我想学习Linux管道是如何工作的!我编写了一个简单的小程序,它使用管道在父进程和子进程之间传递字符串。然而,这个程序导致了一个死锁,我不知道它的原因是什么 代码如下: #include <sys/wait.h> #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define
#include <sys/wait.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define SIZE 100
int
main(int argc, char *argv[])
{
int pfd[2];
int read_pipe=0, write_pipe=0;
pid_t cpid;
char buf[SIZE];
/* PIPE ***************************************
* pipe() creates a pair of file descriptors, *
* pointing to a pipe inode, and places them *
* in the array pointed to by filedes. *
* filedes[0] is for reading, *
* filedes[1] is for writing *
**********************************************/
if (pipe(pfd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
read_pipe=pfd[0];
write_pipe=pfd[1];
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
char * hello = "I am a child process\n";
sleep(1);
// wait until there is some data in the pipe
while (read(read_pipe, buf, SIZE) > 0);
printf("Parent process has written : %s\n", buf);
write(write_pipe, hello, strlen(hello));
close(write_pipe);
close(read_pipe);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
char * hello = "I am a parent process\n";
write(write_pipe, hello, strlen(hello));
while (read(read_pipe, buf, SIZE) > 0);
printf("Child process has written : %s\n", buf);
close(write_pipe);
close(read_pipe);
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义大小100
int
main(int argc,char*argv[])
{
int-pfd[2];
int read_pipe=0,write_pipe=0;
pid_t cpid;
字符buf[大小];
/*烟斗***************************************
*pipe()创建一对文件描述符*
*指向管道索引节点,并放置它们*
*在filedes指向的数组中*
*filedes[0]用于读取*
*filedes[1]用于写入*
**********************************************/
如果(管道(pfd)=-1{
佩罗(“管道”);
退出(退出失败);
}
read_pipe=pfd[0];
写入管道=pfd[1];
cpid=fork();
如果(cpid==-1){
佩罗尔(“福克”);
退出(退出失败);
}
如果(cpid==0){/*子级从管道读取*/
char*hello=“我是一个子进程\n”;
睡眠(1);
//等待,直到管道中有一些数据
而(读取(读取管道、buf、尺寸)>0);
printf(“父进程已写入:%s\n”,buf);
写信(写信,你好,斯特伦(你好));
关闭(写入管道);
关闭(读取管道);
_退出(退出成功);
}else{/*父对象将argv[1]写入管道*/
char*hello=“我是父进程\n”;
写信(写信,你好,斯特伦(你好));
而(读取(读取管道、buf、尺寸)>0);
printf(“子进程已写入:%s\n”,buf);
关闭(写入管道);
关闭(读取管道);
等待(NULL);/*等待子项*/
退出(退出成功);
}
}
在这篇文章中,您可以找到父级和子级之间管道的正确操作。您这里的问题是通信设置不正确
管道应仅用于在一个方向上通信,因此一个进程必须关闭读描述符,另一个进程必须关闭写描述符。否则,将发生的情况是,对“read”(父进程和子进程)的调用,因为它可以检测到管道上存在另一个具有打开写入描述符的进程,当它发现管道为空时(不返回0),将阻塞,直到有人在其中写入内容。所以,你父亲和你儿子的阅读都被阻止了
有两种解决方案:
。创建两个管道,每个方向一个用于通信,并按照上面链接中的说明执行初始化。在这里,您必须记住在发送完消息后关闭写描述符,这样其他进程的读取将返回,或者将循环设置为读取的字节数(而不是读取的返回),这样在读取整个消息时就不会执行另一个调用。例如:
int bread = 0;
while(bread < desired_count)
{
bread += read(read_pipe, buf + bread, SIZE - bread);
}
int-bread=0;
while(面包<所需数量)
{
面包+=读取(读取管道,buf+面包,尺寸-面包);
}
。您可以像以前一样创建一个管道,并修改读取描述符上的标志,使用也可以有O_NONBLOCK,这样当管道中没有信息时,对读取的调用就不会被阻塞。在这里,您需要检查read的返回值,以知道您收到了什么,然后进行累加,直到得到消息的完整长度。此外,您还必须找到一种方法来同步这两个进程,以便它们不会读取不适合它们的消息。我不建议您使用此选项,但如果您想使用条件变量,可以尝试使用它。也许您可以知道是否看到任何printf()输出? 无论如何,如果您想在您的家长和孩子之间建立双向通信,您应该使用两个管道,一个用于从家长到孩子写入数据,另一个用于从孩子到家长写入数据。此外,您的读取循环可能是危险的:如果数据分为两个或更多块,则第二个read()将覆盖第一部分(我从未见过这种情况发生在本地管道上,但例如套接字)。当然,在read()之后,yout不会自动以null结尾,因此仅使用“%s”打印int也可能会导致问题。 我希望这能给你一些尝试的想法