4.1 管道

管道是由pipe函数创建的,提供一个单向数据流。

头文件 #include <unistd.h>
函数原型 int pipe(int fd[2]);
返回值 成功则为0,出错则为-1
函数功能 该函数返回两个文件描述符:fd[0]和fd[1]。fd[0]用来读操作,fd[1]用来写操作
说明 管道只能用于有亲缘关系进程间通讯。要实现非亲缘关系进程间通讯用有名管道FIFO

4.2 管道实现半双工通讯

实现的步骤:

(1)创建管道(fd[0]和fd[1])

(2)fork

(3)父进程关闭管道的读端(fd[0])

(4)子进程关闭管道的写端(fd[1])

(5)父进程往管道的写端(fd[1])写入数据

(6)子进程从管道的读端(fd[0])读出数据

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 #define BUF_MAX_LEN 10

 int main()
 {
     pid_t childpid = ;
     ] = {};
     ] = {};

     // 创建管道
     )
     {
         printf("pipe error");
         ;
     }

     // 创建进程
     childpid = fork();
     )
     {
         printf("fork error\n");
         ;
     }

     // 子进程
     )
     {
         close(pipefd[]); 

         read(pipefd[], buf, BUF_MAX_LEN);
         printf("child:%s\n", buf);

         exit();
     }

     // 父进程
     close(pipefd[]);

     write(pipefd[], "hello", sizeof("hello"));
     printf("parent:%s\n", "hello");

     waitpid(childpid, NULL, );

     ;
 }

4.3 管道实现全双工通讯

实现的步骤:

(1)创建管道1(fd1[0]和fd1[1])、管道2(fd2[0]和fd2[1])

(2)fork

(3)父进程关闭管道1的读端(fd1[0])、关闭管道2的写端(fd2[1])

(4)子进程关闭管道1的写端(fd1[1])、关闭管道2的读端(fd2[0])

(5)父、子进程间通讯

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>

 #define BUF_MAX_LEN 10

 int main()
 {
     pid_t childpid = ;
     ] = {};
     ] = {};
     ] = {};

     // 创建管道fd1
     )
     {
         printf("pipe error");
         ;
     }

     // 创建管道fd2
     )
     {
         printf("pipe error");
         ;
     }

     // 创建进程
     childpid = fork();
     )
     {
         printf("fork error\n");
         ;
     }

     // 子进程
     )
     {
         sleep();
         close(pipefd1[]);
         close(pipefd2[]); 

         read(pipefd1[], buf, BUF_MAX_LEN);
         printf("child read:%s\n", buf);

         write(pipefd2[], "hi", sizeof("hi"));

         exit();
     }

     // 父进程
     close(pipefd1[]);
     close(pipefd2[]);

     write(pipefd1[], "hello", sizeof("hello"));
     read(pipefd2[], buf, BUF_MAX_LEN);
     printf("parent read:%s\n", buf);

     waitpid(childpid, NULL, );

     ;
 }

4.4 popen 和 pclose 函数

头文件 #include <stdio.h>
函数原型 FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
返回值 成功返回文件描述符,失败返回NULL
参数 command shell命令,这行命令将被传到 bin/sh 并使用-c 标志
type r:读到commond的标准输出
  w:写到command的标准输入
说明 popen创建的文件描述符,必须由pclose关闭。
 #include <stdio.h>
 #include <string.h>

 #define BUF_MAX_LEN 100 

 int main()
 {
     FILE *fp = NULL;
     ] = {};

     fp = popen("ls", "r");
     if (fp == NULL)
     {
         printf("popen error\n");
         ;
     }

     while (fgets(buf, BUF_MAX_LEN, fp) != NULL)
     {
         fputs(buf, stdout);
     }

     pclose(fp);

     ;
 }

4.5 FIFO

FIFO由mkfifo函数创建。

头文件

#include <sys/types.h>

#include <sys/stat.h>

函数原型 int mkfifo(const char *pathname, mode_t mode);
返回值 成功返回0,出错返回-1
参数 pathname 一个普通的路径名,它是该FIFO名字
  mode 文件的权限
说明 1.mkfifo函数已隐含O_CREAT | O_EXCL,只能创建一个新的FIFO
  2.如要打开存在的FIFO,首先调用mkfifo,然后判断返回值是否为EEXIST,若返回该错误,再调用open或fopen
  3.FIFO只能读或者写,不能即读又写的,因为它是半双工的
  4.对FIFO写总是追加到末尾,对FIFO读总是从头开始,对FIFO调用lseek,则返回ESPIPE错误
  5.open打开FIFO文件时,如果以只写方式没有打开,则只读方式的open会一直阻塞
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>

 #define FIFO1 "/tmp/fifo1"
 #define FIFO2 "/tmp/fifo2"

 #define BUF_MAX_LEN 10

 int main()
 {
     ;
     ;
     pid_t childpid = ;
     ] = {};

     // 打开2个FIFO
     ) < ) && (errno != EEXIST))
     {
         printf("mkfifo error:cannot open %s\n", FIFO1);
         ;
     }

     ) < ) && (errno != EEXIST))
     {
         unlink(FIFO1);
         printf("mkfifo error:cannot open %s\n", FIFO2);
         ;
     }

     // fork子进程
     childpid = fork();
     )
     {
         unlink(FIFO1);
         unlink(FIFO2);
         printf("fork error\n");
         ;
     }

     // child
     )
     {
         readfd = open(FIFO1, O_RDONLY, );
         writefd = open(FIFO2, O_WRONLY, );  

         write(writefd, "hi", sizeof("hi"));
         read(readfd, buf, BUF_MAX_LEN);
         printf("child recv:%s\n", buf);

         close(readfd);
         close(writefd);

         exit();
     }

     // parent
     writefd = open(FIFO1, O_WRONLY, );
     readfd = open(FIFO2, O_RDONLY, );  

     write(writefd, "hello", sizeof("hello"));
     read(readfd, buf, BUF_MAX_LEN);
     printf("parent recv:%s\n", buf);

     waitpid(childpid, NULL, );

     close(readfd);
     close(writefd);

     unlink(FIFO1);
     unlink(FIFO2);

     ;
 }

4.6 管道和FIFO的区别

(1)创建并打开一个管道只需调用pipe。创建并打开一个FIFO则需要在调用mkfifo后再调用open。

(2)管道在所有进程都关闭后自动关闭。FIFO的名字则只能通过调用unlink才从文件系统中删除。

(3)FIFO有一个名字,可以供无亲缘关系的进程间通讯,管道不可以。

4.7 管道和FIFO的额外属性

(1)将描述符设置成非阻塞。

(2)write写入的字节数小于或等于PIPE_BUF(Posix限制),那么write操作是原子性的;如果写入数据大于PIPE_BUF,那么write操作不保证原子性。O_NOBLOCK标志对write的原子性没有影响

(3)如果向一个没有读打开的管道或FIFO写入,那么内核将产生一个SIGPIPE信号。

第4章 管道和FIFO的更多相关文章

  1. 第4章 管道与FIFO

    4.1 概述 管道只在亲缘进程间使用,FIFO在任意进程间使用 4.2 管道 #include <unistd.h> ]) fd[0]用来读管道,fd[1]用来写管道 1)命令who |  ...

  2. 第四章:管道与FIFO

    4.1:概述 管道是最初的Unix IPC形式,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限在于没有名字,从而只能由亲缘关系的进程使用.这一点随FIFO的加入得改正 ...

  3. 管道和FIFO 一

    管道和FIFO   管道(pipe)       管道在Unix及Linux进程间通信是最基础的,很容易理解.管道就像一个自来水管,一端注入水,一端放出水,水只能在一个方向上流动,而不能双向流动.管道 ...

  4. linux进程间通信-有名管道(FIFO)

    有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...

  5. Linux系统编程——进程间通信:命名管道(FIFO)

    命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...

  6. [转] IPC之管道、FIFO、socketpair

    管道和FIFO作为最初的UNIX IPC形式,现在已用得较少.SocketPair可作为全双工版本的管道,较为常用,这里简单做个笔记 管道 * 只用于有亲缘关系的进程间通信 * 单向,即半双工 (双向 ...

  7. linux 有名管道(FIFO)

    http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...

  8. UNIX环境高级编程——管道和FIFO限制

    系统加于管道和FIFO的唯一限制为: OPEN_MAX     一个进程在任意时刻打开的最大描述符数: PIPE_BUF       可原子的写往一个管道或FIFO的最大数据量. OPEN_MAX的值 ...

  9. UNIX环境高级编程——管道和FIFO的额外属性

    一个描述符能以两种方式设置成非阻塞. (1)调用open时可以指定O_NONBLOCK标志. writefd = open(FIFO1,O_WRONLY | O_NONBLOCK,0); (2)如果一 ...

随机推荐

  1. Git图文教程:从零到上传GitHub项目

    一:安装Git 从Git官网下载.安装客户端 二:本地建立代码仓库 在开始菜单中找到 Git Bash 并打开 配置身份 git config --global user.name "pen ...

  2. js中退出语句break,continue和return 比较

    js中退出语句break,continue和return 比较 在 break,continue和return 三个关键字中, break,continue是一起的,return 是函数返回语句,但是 ...

  3. Vs 2013 单步调试 .net framework 中遇到的问题

    为了可以看清.net framework 的的内部机制,进行单步实际是不错的选择啊,   其它的更多设置可以看其它文章,我这里主要讲问题.     然后就会加载PDB,然后就可以单步进入了. 但是 , ...

  4. 渲染voronoi图

    渲染voronoi图要比计算voronoi图简单. 渲染voronoi图: 方法1: 在pixel shader里,对每一个像素,求哪个种子点到它的距离最近,将此种子点的颜色作为此像素颜色. 当种子点 ...

  5. P1001 第K极值【tyvj】

    /*========================================== P1001 第K极值 内存限制 128MB 代码限制 64KB 描述 Description 给定一个长度为N ...

  6. centos7通过yum安装mysql,并授权远程连接

    安装: CentOS 7的yum源中没有正常安装MySQL的mysql-sever文件,需要去官网上下载(通过安装mysql的yum容器,再通过yum安装mysql) 注:安装前,需要卸载所有的mar ...

  7. CentOS配置ssh无密码登录

      CentOS配置ssh无密码登录的注意点   前提配置:使用root登录修改配置文件:/etc/ssh/sshd_config,将其中三行的注释去掉,如下: 然后重启ssh服务:service s ...

  8. Linux中的free命令

    解释一下Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free Output).例如: FO[2][ ...

  9. ORA-27101:shared memory realm does not exist的问题

    ORA-27101:shared memory realm does not exist的问题 登陆SQLPlus时出现: ORA-01034:ORACLE not avaiable ORA-2710 ...

  10. javassist AOP

    对于AOP,这个概念,不用解释,主要用途很多,我这里主要是为了后续研究如何实现APM做准备.前面研究了动态代理实现AOP,考虑到性能的问题,改用javassist直接修改直接码实现! javassis ...