您的位置:首页 > 运维架构 > Linux

进程间通信匿名管道

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],不能倒过来。

#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 IPC 通信