zoukankan      html  css  js  c++  java
  • linux进程间通信--无名管道

    管道

    只能用于具有亲缘关系的进程之间通信是一个半双工的通信模式,

    具有固定的写读端和写端,管道可以看成一种特殊的文件,对它可以使用普通的read、write等操作

    管道的创建:

    #include <unistd.h>

    int pipe(int fd[2])

    该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,

    然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。

    管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。

    即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。

    如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。

    从管道中读取数据: 如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;

    当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,

    如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);

    或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。

    注:(PIPE_BUF在include/linux/limits.h中定义,不同的内核版本可能会有所不同。Posix.1要求PIPE_BUF至少为512字节,有的是4096)。

    向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。

    如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。 注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,默认动作则是应用程序终止.

    列子:

    无名管道

    1 #include<unistd.h>
    2 #include<sys/types.h>
    3 #include<errno.h>
    4 #include<stdio.h>
    5 #include<stdlib.h>
    6
    7 int main()
    8 {
    9       int pipe_fd[2];
    10       pid_t pid;
    11       char buf_r[100];
    12       char* p_wbuf = NULL ;
    13       int r_num = 0 ;
    14     memset(buf_r , 0 ,sizeof(buf_r));
    15       if(pipe(pipe_fd) < 0) //返回0表示创建失败
    16        {
    17            printf("pipe create error ");
    18            return -1;
    19        }
    20        if( (pid=fork()) == 0) //子进程中 fork()创建子进程会继承父进程的所有,包括管道啦。
    21        {
    22            printf(" ");
    23            close(pipe_fd[1]);//关闭写管道
    24            sleep(1);
    25            if((r_num = read(pipe_fd[0],buf_r,100)) >0) // 返回读写数
    26              {
    27                printf("%d numbers read from the pipe is %s ",r_num ,buf_r);

                        close(pipe_fd[0]);
    29                exit(0);
    30              }
    31        }
    32        else if(pid > 0) //父进程中
    33        {
    34          close(pipe_fd[0]);
    35          if(write(pipe_fd[1], "Hello " , 5) != -1)
    36          printf("parent write1 success! ");
    37          if(write(pipe_fd[1]," Pipe" , 5) != -1)
    38          printf("parent write2 success! ");
    39          close(pipe_fd[1]);
    40           sleep(1);
    41           waitpid(pid ,NULL ,0); //等子进程结束
    42           exit(0);
    43        }
    44      return 0;
    45 }

  • 相关阅读:
    第二阶段团队站立会议06
    第二阶段团队站立会议05
    Spring
    JVM
    线程池
    java内存模型
    线程
    接口与抽象类
    动态绑定,多态,static
    同步异步,并发并行概念的理解
  • 原文地址:https://www.cnblogs.com/yuankaituo/p/4246545.html
Copyright © 2011-2022 走看看