管道是什么:

1. 管道只能用于具有亲缘关系的进程之间通信。

2.管道是一种单工或者说半双工的通信方式,传递信息的方向是固定的,只能由一端传递到另一端。

头文件及函数原型:

#include

int pipe(int fd[2]);

当用pipe 创建管道后,两个文件描述符fd[0],fd[1]就可以使用了,其中fd[0]用于读取,fd[1]用于写入。调用管道pipe返回值0表示成功,返回值-1表示失败。

pipe函数创建管道后,接着fork出子进程,子进程继承父进程管道。

代码举例来看:

#include

#include

#include

#include

#include

#define MAX_DATA_LEN 256

#define DELAY_TIME 1

int main() {

pid_t pid;

char buf[MAX_DATA_LEN];

const char *data="Pipe Test";

int real_read,real_write;

int pipe_fd[2];

memset((void*)buf,0,sizeof(buf));

if(pipe(pipe_fd)<0){

perror("Pipe create error!\n");

exit(1);

}

if ((pid=fork())<0) {

perror("Fork error!\n");

exit(1);

} else if (pid==0) {

close(pipe_fd[1]);

sleep(DELAY_TIME*3);

if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {

printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);

}

close(pipe_fd[0]);

exit(0);

} else {

close(pipe_fd[0]);

sleep(DELAY_TIME);

if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {

printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);

}

close(pipe_fd[1]);

waitpid(pid,NULL,0);

exit(0);

}

}

复制代码

运行输出:

Parent write 9 bytes into pipe: 'Pipe Test'.

Child receive 9 bytes from pipe: 'Pipe Test'.

上述代码只能从父进程向子进程传递,如何从子进程向父进程传递呢?我们看到父进程关闭了管道读取端“close(pipe_fd[0]);”,子进程关闭了管道写入端“close(pipe_fd[1]);”,如果取消关闭这两个端,是否能够实现子进程向父进程传递呢。

父进程先发送,子进程接收,然后子进程再发送,父进程再接收,实现全双工互相通信,期望运行结果如下:

Parent write 9 bytes into pipe: 'Pipe Test'.

Child receive 9 bytes from pipe: 'Pipe Test'.

Child write 9 bytes from pipe: 'Pipe Test'.

Parent receive 9 bytes from pipe: 'Pipe Test'.

修改代码如下:

#include

#include

#include

#include

#include

#define MAX_DATA_LEN 256

#define DELAY_TIME 1

int main() {

pid_t pid;

char buf[MAX_DATA_LEN];

const char *data="Pipe Test";

int real_read,real_write;

int pipe_fd[2];

memset((void*)buf,0,sizeof(buf));

if(pipe(pipe_fd)<0){

perror("Pipe create error!\n");

exit(1);

}

if ((pid=fork())<0) {

perror("Fork error!\n");

exit(1);

} else if (pid==0) {

//close(pipe_fd[1]);

sleep(DELAY_TIME*3);

if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {

printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);

}

if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {

printf("Child write %d bytes into pipe: '%s'.\n",real_write,data);

}

close(pipe_fd[0]);

exit(0);

} else {

//close(pipe_fd[0]);

sleep(DELAY_TIME);

if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {

printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);

}

if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {

printf("Parent receive %d bytes from pipe: '%s'.\n",real_read,buf);

}

close(pipe_fd[1]);

waitpid(pid,NULL,0);

exit(0);

}

}

复制代码

但是实际运行如下:

Parent write 9 bytes into pipe: 'Pipe Test'.

Parent receive 9 bytes from pipe: 'Pipe Test'.

可以看到,父进程发送的数据被父进程自己接收了,子进程读不到数据被阻塞了。显然这种方法不行。

因为管道是单工的,只能固定从一个方向传递到另一个方向。

要实现互相通信,一个管道是不行的,可以创建两个管道,一个管道是父写子读,另一个是子写父读。

代码如下:

#include

#include

#include

#include

#include

#define MAX_DATA_LEN 256

#define DELAY_TIME 1

int main() {

pid_t pid;

char buf[MAX_DATA_LEN];

const char *data="Pipe Test";

int real_read,real_write;

int pipe_fd[2],pipe_fd2[2];

memset((void*)buf,0,sizeof(buf));

if(pipe(pipe_fd)<0){

perror("Pipe create error!\n");

exit(1);

}

if(pipe(pipe_fd2)<0){

perror("Pipe create error!\n");

exit(1);

}

if ((pid=fork())<0) {

perror("Fork error!\n");

exit(1);

} else if (pid==0) {

close(pipe_fd[1]);

close(pipe_fd2[0]);

sleep(DELAY_TIME*3);

if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {

printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);

}

if ((real_write=write(pipe_fd2[1],data,strlen(data)))>0) {

printf("Child write %d bytes into pipe: '%s'.\n",real_write,data);

}

close(pipe_fd[0]);

close(pipe_fd2[1]);

exit(0);

} else {

close(pipe_fd[0]);

close(pipe_fd2[1]);

sleep(DELAY_TIME);

if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {

printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);

}

if ((real_read=read(pipe_fd2[0],buf,MAX_DATA_LEN))>0) {

printf("Parent  receive %d bytes from pipe: '%s'.\n",real_read,buf);

}

close(pipe_fd[1]);

close(pipe_fd2[0]);

waitpid(pid,NULL,0);

exit(0);

}

}

复制代码

运行结果:

Parent write 9 bytes into pipe: 'Pipe Test'.

Child receive 9 bytes from pipe: 'Pipe Test'.

Child write 9 bytes into pipe: 'Pipe Test'.

Parent  receive 9 bytes from pipe: 'Pipe Test'.

可以看到,创建了两个管道 “int pipe_fd[2],pipe_fd2[2];”,

pipe_fd 是父写子读,pipe_fd2是子写父读,通过两个管道,实现了进程的全双工互相通信。

pipe 半双工_linux进程间通信之管道(无名管道pipe)实现全双工双向通信相关推荐

  1. pipe 半双工_linux进程间通讯之管道(无名管道pipe)实现全双工双向通讯

    管道是什么: 1. 管道只能用于具备亲缘关系的进程之间通讯. 2.管道是一种单工或者说半双工的通讯方式,传递信息的方向是固定的,只能由一端传递到另外一端. 头文件及函数原型: #include int ...

  2. linux 进程间通信及makefile 无名管道/有名管道/共享内存/信号/消息队列

    http://www.voidcn.com/article/p-hxvuiypm-mr.html https://www.cnblogs.com/wuyida/archive/2013/02/03/6 ...

  3. linux系统调用创建无名管道,无名管道系统调用

    本文关键字: linux 管道通信,linux 进程通信方式,无名管道 1.管道创建与关闭说明 管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fd[0]和fd[1],其中fd ...

  4. Linux系统无名管道通信实验,Linux进程间通信(二)---管道通信之无名管道及其基础实验...

    管道简介 管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入(其实我更愿意将管道比喻为农村浇地的管子).Linux的管道主要包括两种:无名管道和有名管道.这一节主要讲 ...

  5. 进程间通信方式(一)-- 无名管道、有名管道

    文章目录 1. 进程间通信方式分类 2. 进程间通信实现方式 3. 无名管道 3.1 概念 3.2 相关函数 读写规律 3.3 无名管道实现进程间通信 4. 有名管道 4.1 概念 4.2 创建有名管 ...

  6. linux进程间通信(IPC) ---无名管道

    管道概述 管道(pipe)又称无名管道 无名管道是一种特殊类型的文件,在应用层体现为两个打开的文件描述符 任何一个进程在创建的时候,系统都会,给它分配4G的虚拟内存,分为3G的用户空间和1G的内核空间 ...

  7. linux进程间通讯-无名管道

    文章目录 无名管道 无名管道的创建 -- pipe函数 无名管道的读写规律 无名管道 无名管道概述 管道(pipe)又称无名管道. 无名管道是一种特殊类型的文件,在应用层体现为两个打开的文件描述符.任 ...

  8. 进程间的通信--无名管道

    无名管道是 UNIX 系统 IPC(进程间通信)的最古老形式,所有 UNIX 系统都支持这种通信方式机制 管道的特点: 半双工,数据在同一时刻只能在一个方向上流懂 数据只能从管道的一段写入,另一端读出 ...

  9. 【Linux】管道文件(有名管道、无名管道)

    [Linux]管道文件(有名管道.无名管道) 多进程编程的目的就是为了同时完成多个任务. 例如:一个产品,一个软件,需要n个进程同时执行才能完成,而这些进程之间一定是有所联系的. 因此:多进程工作时, ...

  10. Linux有名管道与无名管道简介

    无名管道 无名管道是最古老的进程通信方式, 有如下两个特点: 1. 只能用于有关联的进程间数据交互, 如父子进程, 兄弟进程, 子孙进程, 在目录中看不到文件节点, 读写文件描述符存在一个 int 型 ...

最新文章

  1. python下线程以及锁
  2. Python学习并发与多线程
  3. 网关和路由器的区别_工业网关和工业路由器的区别?
  4. 最全面的JVM G1学习笔记
  5. JS partial-application
  6. [转]Android 代码混淆和加固 so库 简单教你一行代码实现
  7. java中字母用什么单词赋值_Java初学
  8. css根据屏幕大小切换样式
  9. UVA10917 Walk Through the Forest
  10. 移动端数据爬取和Scrapy框架
  11. libjpeg-turbo 2.1.2 交叉编译
  12. 一阶低通滤波器方程_一阶低通滤波器
  13. NLTK2:词性标注
  14. linux gcc getch,模拟实现getch()
  15. 电商大数据应用之用户画像
  16. Linux使用grep查找文件内容
  17. 模拟科目二倒车入库训练
  18. C#开发金蝶K3插件
  19. layui upload上传文件时动态设置headers参数值
  20. 若依管理系统RuoYi-Vue(前后端分离版)项目启动教程

热门文章

  1. count(1)、count(*)、count(列名) 详解
  2. SAP中生产返工中单独的作业返冲处理分析测试
  3. 智能优化算法应用:基于麻雀搜索优化K-means图像分割算法 - 附代码
  4. 斯科特.H.杨:MIT 课程挑战者 __转
  5. netbeans11安装教程_Netbeans使用教程
  6. 扫描技术的原理与应用(Nmap使用)
  7. mysql insert on duplicate_一条Insert on duplicate引发的血案
  8. php实现加密解密,PHP实现的加密解密处理类
  9. 台湾嵌入式软硬件厂商组建联盟 欲分Gphone一杯羹
  10. asp内乱码,注意不是ajax