c - 死锁 linux 管道

标签 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 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);
    }
}

最佳答案

在此link你会发现 parent 和 child 之间的 PIPEs 的适当操纵。您的问题是通信设置不正确。

PIPE 应该只用于单向通信,因此一个进程必须关闭读描述符,另一个进程必须关闭写描述符。否则将会发生的是调用'read'(在父亲和儿子上),因为它可以检测到另一个进程在 PIPE 上有一个打开的写描述符,当它发现 PIPE 为空时将阻塞(不返回 0),直到有人在其中写入内容。因此,您父亲和您儿子各自的阅读都被阻止了。

有两种解决方法:

。您创建了两个 PIPE,一个用于每个方向的通信,并按照上面链接中的说明执行初始化。在这里你必须记住当你完成发送消息时关闭写描述符,这样其他进程的读取将返回,或者将循环条件设置为读取的字节数(而不是读取的返回),所以你不会'阅读整条消息后,不要再调用一次。例如:

int bread = 0;
while(bread < desired_count)
{
   bread += read(read_pipe, buf + bread, SIZE - bread);
}

。您像以前一样创建一个 PIPE,并使用 fcntl 修改读取描述符上的标志。也有 O_NONBLOCK,所以当 PIPE 中没有信息时,对 read 的调用不会阻塞。在这里您需要检查读取的返回值以了解您收到了一些东西,然后继续累加直到获得消息的完整长度。您还将找到一种方法来同步这两个进程,这样它们就不会读取不适合它们的消息。我不建议你使用这个选项,但如果你想使用条件变量,你可以试试。

关于c - 死锁 linux 管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17022903/

相关文章:

linux - Qt,如何将图标添加到tabWidget 标题?

php - 为什么我在 php exec 中的 bash 中调用 "sh"得到 "echo $0"?

c++ - CMake:如何指定 "install"所依赖的目标?

linux - 如何打印由 sed/awk 更改的行号

c - 为什么我会检测到堆栈粉碎?

c - 为c中的一组趋势线分配不同的权重

linux - 我有一个包含一些列的文件。我想通过对第 1 列值进行分组来对第 2 列进行排序

linux - select() 对/dev/input/mice 上的写入没有响应

c - 在我用 C 语言编写的共享库中允许和不允许导出的函数 - 公共(public)和私有(private)库

c++ - 在带有 makefile 的 C++ 代码中使用 C 库