进程间通信匿名管道
2016-06-08 16:06
501 查看
pipe则是一个底层的调用。与popen函数不同的是,它在两个进程之间传递数据不需要启动一个shell来解释请求命令,同时它还提供对读写数据的更多的控制。
pipe函数的原型如下:
[cpp] view
plain copy
print?
#include <unistd.h>
int pipe(int file_descriptor[2]);
我们可以看到pipe函数的定义非常特别,该函数在数组中墙上两个新的文件描述符后返回0,如果返回返回-1,并设置errno来说明失败原因。
数组中的两个文件描述符以一种特殊的方式连接起来,数据基于先进先出的原则,写到file_descriptor[1]的所有数据都可以从file_descriptor[0]读回来。由于数据基于先进先出的原则,所以读取的数据和写入的数据是一致的。
特别提醒:
1、从函数的原型我们可以看到,它跟popen函数的一个重大区别是,popen函数是基于文件流(FILE)工作的,而pipe是基于文件描述符工作的,所以在使用pipe后,数据必须要用底层的read和write调用来读取和发送。
2、不要用file_descriptor[0]写数据,也不要用file_descriptor[1]读数据,其行为未定义的,但在有些系统上可能会返回-1表示调用失败。数据只能从file_descriptor[0]中读取,数据也只能写入到file_descriptor[1],不能倒过来。
当写数据的管道没有关闭,而又没有数据可读时,read调用通常会阻塞,但是当写数据的管道关闭时,read调用将会返回0而不是阻塞。注意,这与读取一个无效的文件描述符不同,read一个无效的文件描述符返回-1。它的一个缺点,就是通信的进程,它们的关系一定是父子进程的关系。
pipe函数的原型如下:
[cpp] view
plain copy
print?
#include <unistd.h>
int pipe(int file_descriptor[2]);
我们可以看到pipe函数的定义非常特别,该函数在数组中墙上两个新的文件描述符后返回0,如果返回返回-1,并设置errno来说明失败原因。
数组中的两个文件描述符以一种特殊的方式连接起来,数据基于先进先出的原则,写到file_descriptor[1]的所有数据都可以从file_descriptor[0]读回来。由于数据基于先进先出的原则,所以读取的数据和写入的数据是一致的。
特别提醒:
1、从函数的原型我们可以看到,它跟popen函数的一个重大区别是,popen函数是基于文件流(FILE)工作的,而pipe是基于文件描述符工作的,所以在使用pipe后,数据必须要用底层的read和write调用来读取和发送。
2、不要用file_descriptor[0]写数据,也不要用file_descriptor[1]读数据,其行为未定义的,但在有些系统上可能会返回-1表示调用失败。数据只能从file_descriptor[0]中读取,数据也只能写入到file_descriptor[1],不能倒过来。
#include <iostream> #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #define K 1024 #define MSGLEN 128*K using namespace std; int main() { int ret=-1; pid_t pid; int fd[2],bytes; int* read_fd=&fd[0]; int* write_fd=&fd[1]; char msg[MSGLEN]="hello,ipc message!"; char buffer[10*K]; ret=pipe(fd); if(-1==ret){ printf("[%d] pipe create failed!\n",getpid());return -1;} pid=fork(); if(-1==pid){ printf("[%d] fork failed!\n",getpid());return -1;} else if(pid>0) { printf("[%d] child pid %d \n",getpid(),pid); close(*write_fd); while(1) { bzero(buffer,sizeof(buffer)); bytes=read(*read_fd,buffer,sizeof(buffer)); if(bytes<=0) {printf("[%d] no msg ,the write_fd closed \n",getpid()); break;} printf("[%d] get message %d bytes : %s \n",getpid(),bytes,buffer); } return 0; } else { printf("[%d] parent pid %d \n",getpid(),getppid()); close(*read_fd); int len=MSGLEN; while(len) { ret=write(*write_fd,msg,len); if(ret>0) { printf("[%d] send message %d bytes \n",getpid(),ret); len-=ret; } else{sleep(10);} } return 0; } return 0; }
当写数据的管道没有关闭,而又没有数据可读时,read调用通常会阻塞,但是当写数据的管道关闭时,read调用将会返回0而不是阻塞。注意,这与读取一个无效的文件描述符不同,read一个无效的文件描述符返回-1。它的一个缺点,就是通信的进程,它们的关系一定是父子进程的关系。
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- Linux 下无损图片压缩小工具介绍