美文网首页
Linux系统编程—有名管道

Linux系统编程—有名管道

作者: 良许Linux | 来源:发表于2020-10-09 21:27 被阅读0次

    ▋****1. 管道的概念

    管道,又名「无名管理」,或「匿名管道」,管道是一种非常基本,也是使用非常频繁的IPC方式。

    1.1 管道本质

    • 管道的本质也是一种文件,不过是伪文件,实际上是一块内核缓冲区,大小4K;
    • 管道创建以后会产生两个文件描述符,一个是读端,另一个是写端;
    • 管道里的数据只能从写端被写入,从读端被读出;

    1.2 管道原理

    管道是内核的一块缓冲区,更具体一些,是一个环形队列。数据从队列的一端写入数据,另一端读出,如下图示:

    1.3 管道的优点

    简单

    1.4 管道的缺点

    • 只能单向通信,如果需要双向通信则需要建立两个管道;
    • 只能应用于具有血缘关系的进程,如父子进程;
    • 缓冲区大小受限,通常为1页,即4k;

    ▋****2. 管道的创建

    管道创建三步曲:

    a. 父进程调用pipe函数创建管道;

    b. 父进程调用fork函数创建子进程;

    c. 父进程关闭fd[0],子进程关闭fd[1];

    具体如下图所示:

    ▋****3. 管道的读写行为

    a. 管道的缓冲区大小固定为4k,所以如果管道内数据已经写满,则无法再写入数据,进程的write调用将阻塞,直到有足够的空间再写入数据;

    b. 管道的读动作比写动作要快,数据一旦被读走了,管道将释放相应的空间,以便后续数据的写入。当所有的数据都读完之后,进程的read()调用将阻塞,直到有数据再次写入。

    ▋****4. 例程

    父子间通信:

     1#include <stdio.h>
     2#include <sys/types.h>
     3#include <unistd.h>
     4#include <string.h>
     5
     6int main()
     7{
     8    int fd[2];
     9    pid_t pid;
    10    char buf[1024];
    11    char *data = "hello world!";
    12
    13    /* 创建管道 */
    14    if (pipe(fd) == -1) {
    15        printf("ERROR: pipe create failed!\n");
    16        return -1;
    17    }
    18
    19    pid = fork();
    20    if (pid == 0) {
    21        /* 子进程 */
    22        close(fd[1]);   // 子进程读取数据,关闭写端
    23        read(fd[0], buf, sizeof(buf));  // 从管道读数据
    24        printf("child process read: %s\n", buf);
    25        close(fd[0]);
    26    } else if (pid > 0) {
    27        /* 父进程 */
    28        close(fd[0]);   //父进程写数据,关闭读端
    29        write(fd[1], data, strlen(data));   // 向管道写数据
    30        printf("parent process write: %s\n", data);
    31        close(fd[1]);
    32    }
    33
    34    return 0;
    35}
    

    兄弟间通信:

     1#include <stdio.h>
     2#include <sys/types.h>
     3#include <unistd.h>
     4#include <string.h>
     5#include <sys/wait.h>
     6
     7int main ()
     8{
     9    int fd[2];
    10    int i = 0;
    11    pid_t pid;
    12    char buf[1024];
    13    char *data = "hello world!";
    14
    15    /* 创建管道 */
    16    if (pipe(fd) == -1) {
    17        printf("ERROR: pipe create failed!\n");
    18        return -1;
    19    }
    20
    21    for (i = 0; i < 2; i++) {
    22        pid = fork();
    23        if (pid == -1) {
    24            printf("ERROR: fork error!\n");
    25            return -1;
    26        } else if (pid == 0) {
    27            break;
    28        }
    29    }
    30
    31    /* 通过i来判断创建的子进程及父进程 */
    32    if (i == 0) {
    33        /* 第一个子进程,兄进程 */
    34        close(fd[0]);   // 兄进程向弟进程写数据,关闭读端
    35        write(fd[1], data, strlen(data));
    36        printf("elder brother send: %s\n", data);
    37        close(fd[1]);
    38    } else if (i == 1) {
    39        /* 第二个子进程,弟进程 */
    40        close(fd[1]);
    41        read(fd[0], buf, sizeof(buf));
    42        printf("younger brother receive: %s\n", buf);
    43        close(fd[0]);
    44    } else {
    45        /* 父进程 */
    46        close(fd[0]);
    47        close(fd[1]);
    48        for (i = 0; i < 2; i++) {
    49            wait(NULL);
    50        }
    51    }
    52
    53    return 0;
    54}
    

    更多精彩内容,请关注公众号良许Linux,公众内回复1024可免费获得5T技术资料,包括:Linux,C/C++,Python,树莓派,嵌入式,Java,人工智能,等等。公众号内回复进群,邀请您进高手如云技术交流群。


    最后,最近很多小伙伴找我要Linux学习路线图,于是我根据自己的经验,利用业余时间熬夜肝了一个月,整理了一份电子书。无论你是面试还是自我提升,相信都会对你有帮助!目录如下:

    免费送给大家,只求大家金指给我点个赞!

    电子书 | Linux开发学习路线图

    也希望有小伙伴能加入我,把这份电子书做得更完美!

    有收获?希望老铁们来个三连击,给更多的人看到这篇文章

    推荐阅读:

    相关文章

      网友评论

          本文标题:Linux系统编程—有名管道

          本文链接:https://www.haomeiwen.com/subject/klerpktx.html