1.写端存在,没有关闭

1)当管道中没有数据时候,read函数会阻塞;

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>int main(int argc, const char *argv[])
{int pfd[2]; // 管道创建(pipe)在进程创建(fork)之前if(pipe(pfd)<0) // 保证父子进程 共用同一管道做传输{perror("pipe"); return -1;}printf("无名管道创建成功\n");char buf[128] = "";ssize_t res = 0;pid_t pid = fork();if(pid > 0) // 父进程{printf("this is parent %d\n", getpid());   while(1){bzero(buf, sizeof(buf));scanf("%s", buf);getchar();res = write(pfd[1], buf, sizeof(buf)); // 写入到管道if(res < 0){perror("write");return -1;}printf("写入成功 res = %ld\n", res);}}else if(0 == pid) // 子进程{printf("this is child %d\n", getpid());while(1){bzero(buf, sizeof(buf));res = read(pfd[0], buf, sizeof(buf)); // 管道中没有数据 read函数阻塞// 注意 管道文件是特殊文件,没有数据会阻塞;不会像普通文件,读不到返回0if(res<0) // 读到管道中有数据时,直接打印出来{perror("read");return -1;}printf("读取成功 res = %ld  %s\n", res, buf);}}else{perror("fork");return -1;}return 0;
}

测试结果:

ubuntu@ubuntu:10.14$ ./a.out
无名管道创建成功
this is parent 30896
this is child 30897

父进程阻塞在scanf函数;子进程阻塞在read函数。

ubuntu@ubuntu:10.14$ ./a.out
无名管道创建成功
this is parent 30896
this is child 30897
qqqqqq
写入成功 res = 128
读取成功 res = 128  qqqqqq
wwwwwwwwwww
写入成功 res = 128
读取成功 res = 128  wwwwwwwwwww
33333333
写入成功 res = 128
读取成功 res = 128  33333333
^C
ubuntu@ubuntu:10.14$

写端存在,没有关闭

2)当管道中存储了11个数据,read函数读取5个,实际读取5个

3)当管道中存储了1个数据,read函数读取5个,实际读取1个

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>int main(int argc, const char *argv[])
{//由于父子进程如果想要通信,必须读写同一根管道//所以利用子进程会克隆父进程的文件描述符表的原理//我们在fork之前创建这个无名管道int pfd[2];if(pipe(pfd) < 0){perror("pipe");return -1;}printf("无名管道创建成功 r:%d w:%d\n",pfd[0], pfd[1]);char buf[128] = "";ssize_t res = 0;pid_t pid = fork(); if(pid > 0){//父进程中运行printf("this is parent %d\n", getpid());strcpy(buf, "hello world");//将数据写入到管道中res=write(pfd[1], buf, strlen(buf));if(res < 0){perror("write");return -1;}printf("写入成功 res=%ld\n", res);}else if(0 == pid){//子进程中运行 printf("this is child %d\n", getpid());while(1){sleep(1);bzero(buf, sizeof(buf));//读取管道中的数据,当管道中没有数据的时候read函数阻塞res = read(pfd[0], buf, 5);if(res < 0){perror("read");return -1;}printf("读取数据成功:%ld:%s\n", res, buf);}}else{perror("fork");return -1;}return 0;
}

测试结果:

2)当管道中存储了11个数据,read函数读取5个,实际读取5个

3)当管道中存储了1个数据,read函数读取5个,实际读取1个

ubuntu@ubuntu:10.14$ ./a.out
无名管道创建成功 r:3 w:4
this is parent 30862
写入成功 res=11
ubuntu@ubuntu:10.14$ this is child 30863
读取数据成功:5:hello
读取数据成功:5: worl
读取数据成功:1:dubuntu@ubuntu:10.14$
ubuntu@ubuntu:10.14$
ubuntu@ubuntu:10.14$

父进程退出,子进程成为孤儿进程,此时代码阻塞在read函数处,并且在后端休眠。

30446  30834  30834  30834 pts/5     30868 Ss    1000   0:00 /bin/bash1  30863  30862  30834 pts/5     30868 S     1000   0:00 ./a.out30834  30868  30868  30834 pts/5     30868 R+    1000   0:00 ps -ajx
ubuntu@ubuntu:10.14$

2. 当所有写端均被关闭(父子进程均有写端)

1)从管道中读取数据,先会正常的将管道中的所有数据读取完毕,管道中没有数据,read函数不会阻塞,且立即返回0;

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>int main(int argc, const char *argv[])
{//由于父子进程如果想要通信,必须读写同一根管道//所以利用子进程会克隆父进程的文件描述符表的原理//我们在fork之前创建这个无名管道int pfd[2];if(pipe(pfd) < 0){perror("pipe");return -1;}printf("无名管道创建成功 r:%d w:%d\n",pfd[0], pfd[1]);char buf[128] = "";ssize_t res = 0;pid_t pid = fork(); if(pid > 0){//父进程中运行printf("this is parent %d\n", getpid());bzero(buf, sizeof(buf));scanf("%s", buf);getchar();//将数据写入到管道中res=write(pfd[1], buf, strlen(buf));if(res < 0){perror("write");return -1;}printf("写入成功 res=%ld\n", res);printf("准备关闭所有写端\n");close(pfd[1]);    //子进程刚启动就关闭了写端,父进程在当前位置关闭写端}else if(0 == pid){//子进程中运行 close(pfd[1]);printf("this is child %d\n", getpid());while(1){bzero(buf, sizeof(buf));//读取管道中的数据,当管道中没有数据的时候read函数阻塞res = read(pfd[0], buf, 1);if(res < 0){perror("read");return -1;}if(0 == res){printf("所有写端均被关闭,且管道中的数据读取完毕\n");break;}printf("读取数据成功:%ld:%s\n", res, buf);}}else{perror("fork");return -1;}return 0;
}

测试结果:

ubuntu@ubuntu:10.14$ ./a.out
无名管道创建成功 r:3 w:4
this is parent 30964
this is child 30965
qqqqqqq
写入成功 res=7
准备关闭所有写端
ubuntu@ubuntu:10.14$ 读取数据成功:1:q
读取数据成功:1:q
读取数据成功:1:q
读取数据成功:1:q
读取数据成功:1:q
读取数据成功:1:q
读取数据成功:1:q
所有写端均被关闭,且管道中的数据读取完毕
ubuntu@ubuntu:10.14$

进程间通信 管道特性(无名管道演示)当向管道中读出数据的时候:相关推荐

  1. Linux系统编程27:进程间通信之管道的基本概念和匿名管道与命名管道及管道特性

    文章目录 (1)管道是什么 (2)匿名管道 A:读端和写端 B:建立匿名管道的函数 C:最简单的进程间通信-演示 D:管道四大特性 E:管道的特点 F:从内核角度理解管道 G:管道总结 (3)命名管道 ...

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

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

  3. 17、有名管道与无名管道之间的区别

    1)无名管道:管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道:只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程). 单独构成一种独立的文件系统:管道对于管道两端的进程而 ...

  4. 有名管道和无名管道的区别

    1)无名管道:管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道:只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程). 单独构成一种独立的文件系统:管道对于管道两端的进程而 ...

  5. 有名管道和无名管道的介绍

    文章目录 前言 一.无名管道 1.概念介绍 2.相关函数介绍 3.关于无名管道的一些说明 4.无名管道编程实战 二.有名管道 1.概念 2.编程实战 总结 前言 在进程间通信的几种方式中,管道可谓是最 ...

  6. linux系统调用创建无名管道,linux 无名管道pipe和有名管道FIFO

    1.管道(pipe) 管道是进程间通信的主要手段之一.一个管道实际上就是个只存在于内存中的文件,对这个文件的操作要通过两个已经打开文件进行,它们分别代表管道的两端.管道是一种特殊的文件,它不属于某一种 ...

  7. 管道——(1)有名管道和无名管道

    一.引子 之前,两个进程间要发送消息,是通过信号来完成的.创建通知事件,通过它引起响应,但是传送的信息只是一个信号值而已. 如果两个进程需要交换更有用.复杂的信息,就需要用到--管道. 管道--一个进 ...

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

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

  9. linux管道文件的实现原理,管道(无名管道)通信机制原理和实现详解

    管道(pipe)允许两个进程进行通信,是早期 UNIX 系统最早使用的一种IPC 机制.管道为进程之间的相互通信提供了一种较为简单的方法,尽管也有一定的局限性. 在实现管道时,应该考虑以下四个问题: ...

最新文章

  1. 关于实验中的makefile相关知识
  2. crash工具解析_IDA反汇编静态调试Android平台C++的so文件Crash入门
  3. 2018年AI和ML(NLP、计算机视觉、强化学习)技术总结和2019年趋势(下)
  4. java网络通信:HTTP协议
  5. 计算机发展史的内容概述,计算机及其发展史概述
  6. 常用CSS优化总结——网络性能与语法性能建议
  7. mysql 查看索引
  8. Jquery 安装到Visual Studio 2008
  9. 环回测试能够提供什么信息_以太网测试仪的主要功能有哪些?
  10. 大数据学习——mapreduce共同好友
  11. Python数据结构与算法分析(第二版)答案 - 第二章(仅供参考)
  12. php中文网怎么修改头像,thinkphp 头像上传在线剪切编辑问题 (使用美图秀秀头像编辑器组件)...
  13. 狂神说的全部笔记_聪明人的方格笔记术
  14. 详解变频器、逆变器工作原理
  15. 【无人机设计与开发】推荐几个无人机网址
  16. Parameter... parameter
  17. 【Note】二十四节气英文表达(solar term)
  18. 程序员自学编程,推荐一些高质量自学网站?
  19. 深度学习入门笔记(二十):经典神经网络(LeNet-5、AlexNet和VGGNet)
  20. 金华职称计算机考试中心,郑金华

热门文章

  1. 本题要求编写函数,将输入字符串的前3个字符移到最后
  2. 集群性能常用计算公式
  3. 第十三届蓝桥杯赛前的一点总结
  4. 类变量、成员变量、局部变量存放位置
  5. 怎样判断手机号码是移动的还是联通的
  6. 双骰子游戏——简单语句实现,do while循环
  7. 图像分割中OTSU算法
  8. CISAW认证,与CISP认证有啥区别?
  9. TOPERS中间件之一---嵌入式组件系统TECS
  10. 第三次(一):对比《阴阳师》《小冰冰传奇》两款游戏