zoukankan      html  css  js  c++  java
  • Linux系统编程—管道

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

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

    1.1 管道本质

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

    1.2 管道原理

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

    img

    1.3 管道的优点

    简单

    1.4 管道的缺点

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

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

    管道创建三步曲:

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

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

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

    具体如下图所示:

    img

    ▋****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!
    ");
    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
    ", 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
    ", 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!
    ");
    18        return -1;
    19    }
    20
    21    for (i = 0; i < 2; i++) {
    22        pid = fork();
    23        if (pid == -1) {
    24            printf("ERROR: fork error!
    ");
    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
    ", 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
    ", 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,人工智能,等等。公众号内回复进群,邀请您进高手如云技术交流群。

    img


    公众号:良许Linux

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

  • 相关阅读:
    剑桥雅思写作高分范文ESSAY50
    剑桥雅思写作高分范文ESSAY49
    剑桥雅思写作高分范文ESSAY48
    剑桥雅思写作高分范文ESSAY47
    剑桥雅思写作高分范文ESSAY46
    剑桥雅思写作高分范文ESSAY45
    剑桥雅思写作高分范文ESSAY44
    剑桥雅思写作高分范文ESSAY43
    剑桥雅思写作高分范文ESSAY42
    剑桥雅思写作高分范文ESSAY41
  • 原文地址:https://www.cnblogs.com/yychuyu/p/13794763.html
Copyright © 2011-2022 走看看