• 3.1 进程间通信之管道


    一、引言

    管道作用于有血缘关系的进程间的通信,完成数据传递。实际为内核使用环形队列机制,借助内核缓冲区(4k)实现。有如下特质:

    1) 其本质是一个伪文件(实为内核缓冲区)

    2) 由两个文件描述符引用,一个表示读端,一个表示写端。可定义一个文件描述符数组,存取。

    3) 规定数据从管道的写端流入管道,从读端流出。

    4) 数据自己读不能自己写,数据一旦被读走,便不在管道中存在,不可反复读取。 由于管道采用半双工通信方式。因此,数据也只能在一个方向上流动。

    5) 只能在有公共祖先的(血缘关系的)进程间使用管道。

    二、pipe函数

    调用pipe系统函数即可创建一个管道,其函数原型为:

    int pipe(int fd[2]);
    成功:
    0;失败:-1,设置errno

    向管道文件读写数据其实是在读写内核缓冲区,函数参数数组包含pipe使用的两个文件的描述符:fd[0] → r; fd[1] → w,就像0对应标准输入,1对应标准输出一样。注意:在pipe使用时,无需open,但需手动close

    管道方法通信流程:

    1) 父进程调用pipe函数创建管道,得到两个文件描述符fd[0]fd[1]指向管道的读端和写端。

    2) 父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。

    3) 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出。由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信。

    三、例程

     1 #include <unistd.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <stdio.h>
     5 #include <sys/wait.h>
     6 
     7 int main(void)
     8 {
     9     pid_t pid;
    10     char buf1[1024];
    11     int fd[2];
    12     int len;
    13     char *buf2 = "hello world
    ";
    14     
    15    if (pipe(fd) == -1) //创建管道 
    16        printf("pipe error
    ");
    17 
    18    pid = fork(); //创建进程
    19    if (pid < 0) {
    20        printf("fork error
    ");
    21    } 
    22    else if (pid == 0) { 
    23         close(fd[1]);  //子进程关闭写端
    24         len = read(fd[0], buf1, sizeof(buf));//读取管道数据到buf中
    25         write(STDOUT_FILENO, buf1, len);//将buf数据写入标准输出
    26         close(fd[0]); //注意要close
    27        } 
    28     else {
    29               close(fd[0]);//父进程关闭读端
    30                  write(fd[1], buf2, strlen(buf2));//向管带的写端写入字符串p
    31           wait(NULL);  //等待子进程释放
    32           close(fd[1]);
    33    }
    34     
    35     return 0;
    36 }

    编译执行结果:

    补充:

    读管道:

    1)管道中有数据,read返回实际读到的字节数。

    2)管道中无数据:

    (1) 管道写端被全部关闭,read返回0 (好像读到文件结尾)

    (2) 写端没有全部被关闭,read阻塞等待(不久的将来可能有数据递达,此时会让出cpu)

    写管道:

    1)管道读端全部被关闭, 进程异常终止(也可使用捕捉SIGPIPE信号,使进程不终止)

    2)管道读端没有全部关闭:

    (1) 管道已满,write阻塞。

    (2) 管道未满,write将数据写入,并返回实际写入的字节数。

    缓冲大小:使用ulimit –a 命令来查看当前系统中创建管道文件所对应的内核缓冲区大小

  • 相关阅读:
    审 讯 技巧
    带参数的多线程的方式
    通达信日线 数据格式
    visual studio 2012 update3
    单实例运行tz
    维特比算法
    Kooboo CMS的安装步骤
    年龄
    富文本编辑器---非常实用的
    printf 打印 unit32_t
  • 原文地址:https://www.cnblogs.com/lxl-lennie/p/10237740.html
Copyright © 2020-2023  润新知