【linux高级程序设计】(第九章)进程间通信-管道 1
2015-07-27 15:19
651 查看
Linux操作系统所支持的主要进程间的通信机制。
上面这种管道,将一个命令的输出作为另一个命令的输入,而这种管道是临时的,命令执行完成后将自动消失,称为无名管道。
int pipe (int __pipedes[2]) :创建无名管道
如果执行成功,pipe将存储两个整型文件描述符于__pipedes[0](只能读)和__pipedes[1](只能写)中,它们分别指向管道的两端。如果需要双工的,需要建立两个管道。
(1)以阻塞方式读取无名管道,且当前没有进程可以访问写端
如果管道现有数据无数据,立即返回0
如果管道现有数据大于要读出的数据,立即读取期望大小的数据
如果管道现有数据小于要读出的数据,立即读取所有数据
第一种情况
第二、三种情况
(2)以阻塞方式读取无名管道,且当前有进程可以访问写端
管道中无任何数据,读操作阻塞
管道中有数据,现有数据大小小于期望读出值,读出现有数据并返回。
管道中有数据,现有数据大小大于期望读出值,读出期望大小的数据并返回。
第一种情况
阻塞了,通过Ctrl+C退出。
第二、三种情况(其实跟之前的代码比就少了一句close)
(3)如果以阻塞方式写无名管道,如果当前没有可以访问读端的进程,写操作将收到SIGPIPE信号,write返回-1.
(4)如果以阻塞方式写无名管道,如果当前管道已经满,则阻塞当前进程。多个进程试图写管道需要避免竞争的机制。写入建议小于PIPE_BUF(默认4096)大小。
(5)如果以O_NDELAY或O_NONBLOCK设置了管道的读端,如果管道中没有数据,将立即返回-1,且置errno为EAGAIN错误
(6)如果以O_NDELAY或O_NONBLOCK设置了管道的写端,如果管道中没有足够空间,将立即返回-1,且置errno为EAGAIN错误
无名管道 PIPE
cat test.txt| grep hello
上面这种管道,将一个命令的输出作为另一个命令的输入,而这种管道是临时的,命令执行完成后将自动消失,称为无名管道。
int pipe (int __pipedes[2]) :创建无名管道
如果执行成功,pipe将存储两个整型文件描述符于__pipedes[0](只能读)和__pipedes[1](只能写)中,它们分别指向管道的两端。如果需要双工的,需要建立两个管道。
读写无名管道
必须确认还存在一个进程,可以使进程自己。默认以阻塞方式读写管道,如果修改可以使用fcntl函数实现。(1)以阻塞方式读取无名管道,且当前没有进程可以访问写端
如果管道现有数据无数据,立即返回0
如果管道现有数据大于要读出的数据,立即读取期望大小的数据
如果管道现有数据小于要读出的数据,立即读取所有数据
第一种情况
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(void) { int p[2]; pipe(p); close(p[1]); //断开当前进程与管道写端的联系 char buf[128]; memset(buf, '\0', 128); int ret = -1; ret = read(p[0], buf, 128); //阻塞读,无数据,无进程关联写,立即返回 printf("buf = %s\n", buf); }
第二、三种情况
#include<stdio.h> #include<unistd.h> #include<string.h> #include<stdlib.h> int main(void) { int p[2]; pipe(p); write(p[1], "helloworld", 10); //写入10个字节 close(p[1]); //断开当前进程与管道写端的联系 char buf[128]; memset(buf, '\0', 128); int ret = -1; ret = read(p[0], buf, 3); //有数据,且大于期望读出值 printf("first, ret = %d, buf = %s\n", ret, buf); ret = read(p[0], buf, 15); //有数据,且小于期望读出值 printf("second, ret = %d, buf = %s\n", ret, buf); }
(2)以阻塞方式读取无名管道,且当前有进程可以访问写端
管道中无任何数据,读操作阻塞
管道中有数据,现有数据大小小于期望读出值,读出现有数据并返回。
管道中有数据,现有数据大小大于期望读出值,读出期望大小的数据并返回。
第一种情况
int main(void) { int p[2]; pipe(p); char buf[128]; memset(buf, '\0', 128); int ret = -1; ret = read(p[0], buf, 128); //阻塞读,无数据,无进程关联写,立即返回 printf("buf = %s\n", buf); }
阻塞了,通过Ctrl+C退出。
第二、三种情况(其实跟之前的代码比就少了一句close)
int main(void) { int p[2]; pipe(p); write(p[1], "helloworld", 10); //写入10个字节 char buf[128]; memset(buf, '\0', 128); int ret = -1; ret = read(p[0], buf, 3); //有数据,且大于期望读出值 printf("first, ret = %d, buf = %s\n", ret, buf); ret = read(p[0], buf, 15); //有数据,且小于期望读出值 printf("second, ret = %d, buf = %s\n", ret, buf); }
(3)如果以阻塞方式写无名管道,如果当前没有可以访问读端的进程,写操作将收到SIGPIPE信号,write返回-1.
#include<stdio.h> #include<string.h> #include<signal.h> void handler(int sig) { if(SIGPIPE == sig) printf("recv SIGPIPE\n"); } int main(void) { int p[2]; signal(SIGPIPE, handler); pipe(p); close(p[0]); //断开当前进程与管道读端的联系 int ret = -1; ret = write(p[1], "helloworld", 10); //写入10个字节 printf("ret = %d\n", ret); }
(4)如果以阻塞方式写无名管道,如果当前管道已经满,则阻塞当前进程。多个进程试图写管道需要避免竞争的机制。写入建议小于PIPE_BUF(默认4096)大小。
(5)如果以O_NDELAY或O_NONBLOCK设置了管道的读端,如果管道中没有数据,将立即返回-1,且置errno为EAGAIN错误
(6)如果以O_NDELAY或O_NONBLOCK设置了管道的写端,如果管道中没有足够空间,将立即返回-1,且置errno为EAGAIN错误
相关文章推荐
- linux内核分析笔记----中断和中断处理程序
- Linux地图服务器部署
- linux程序设计——个人总结
- C++遍历目录,并把目录里超过7天的文件删除(跨平台windows&linux)
- CentoOS6.6安装netcat
- Linux环境下编程(二)——线程基础概念
- 正确Linux新手很实用20命令
- CentOS下SNMP服务安装
- Linux下RPM软件包的安装及卸载
- linux mint gcc 编译第一个c程序
- centos虚机出现挂载不上光驱
- linux文件io
- linux 解压cpio.gz文件
- CentOS7安装cuda7
- Linux_多核系统下绑定进程或线程到指定CPU_核执行
- Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)
- 查看centos系统版本
- Linux中fork()函数详解
- Linux中fork()函数详解 分类: Ubuntu学习笔记 2015-07-27 13:56 9人阅读 评论(0) 收藏
- 使用SAMBA协议实现Linux与Windows系统之间的文件共享