Giu*_*Pes 2 c unix linux pipe linux-kernel
我想了解Linux管道是如何工作的!我写了一个小而简单的程序,它使用管道在父进程和子进程之间传递字符串.但是,该程序导致死锁,我不明白它的原因是什么.
这是代码:
#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);
}
}
Run Code Online (Sandbox Code Playgroud)
在此链接中,您将找到父母和孩子之间正确的PIPE操作.您的问题是通信未正确设置.
PIPE应仅用于在一个方向上进行通信,因此一个进程必须关闭读取描述符,另一个进程必须关闭写入描述符.否则会发生的事情是调用'read'(父亲和儿子),因为它可以检测到PIPE上有另一个带有开放写入描述符的进程,当它发现PIPE为空时将阻塞(不归0),直到有人在里面写东西.所以,你父亲和你的儿子在各自的阅读中都被封锁了.
有两种解决方案:
.您创建了两个PIPE,一个用于每个方向的通信,并按照上面的链接中的说明执行初始化.在这里你必须记住在完成发送消息后关闭写描述符,这样另一个进程'read将返回,或者将循环调整为读取的字节数(不是返回读取),所以你赢了'当您阅读整个消息时,执行另一个呼叫.例如:
int bread = 0;
while(bread < desired_count)
{
bread += read(read_pipe, buf + bread, SIZE - bread);
}
Run Code Online (Sandbox Code Playgroud)
你像你一样创建了一个PIPE,并修改了读取描述符上的标志,使用fcntl也有O_NONBLOCK,所以当PIPE中没有信息时,read的调用不会被阻塞.在这里,您需要检查读取的返回值以了解您收到的内容,然后加起来直到您获得完整的消息长度.此外,您将找到一种方法来同步这两个进程,以便它们不会读取不适合它们的消息.我不建议您使用此选项,但如果您想使用条件变量,可以尝试使用此选项.