进程间通信系列--管道

进程间通信系列--管道

管道可以说是最古老的IPC形式,所谓管道,是指进程间建立的一条通信的通道,从本质上看,管道是UNIX文件概念的推广管道通信的介质是文件,先看一下管道的特点:

1.管道的特点:

(1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

(2)无名管道只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);后来发展了FIFO(也称有名管道)

(3)单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。

(4)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

2.无名管道API及操作:

头文件:#include

数据成员:int pipe_fd[2];

管道创建:int pipe(int fd[2])

该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。

管道读写:

管道两端可分别用描述字fd[0]以及fd[1]来描述,管道读端:fd[0],管道写端:fd[1];

读管道规则:

关闭管道的写端:close (fd[WRITE]);

读出:read(fd[READ],string,strlen(string));

读出后关闭管道的读端:close(fd[REAd]);

写管道规则:

关闭管道的读端:close(fd[REAd]);

写入:write(fd[WRITE],string,strlen(string));

写入后关闭管道的写端:close (fd[WRITE]);

下面练习一个简单的单管道通信:

父进程写数据,子进程负责读出数据

view plaincopy to clipboardprint?
/**************

* readtest.c *

**************/

#include
#include
#include

#define READ 0
#define WRITE 1

main()
{
int pipe_fd[2];
pid_t pid;
char r_buf[100];
char w_buf[32];
char* p_wbuf;
int r_num;
int cmd;
memset(r_buf,0,sizeof(r_buf));
memset(w_buf,0,sizeof(r_buf));
p_wbuf=w_buf;
if(pipe(pipe_fd)<0)
{
printf("pipe create error ");
return -1;
}

if((pid=fork())==0) //子进程读
{
close(pipe_fd[WRITE]);
sleep(3); //确保父进程关闭写端
r_num=read(pipe_fd[READ],r_buf,100);
printf( "read num is %d the data read from the pipe is %s n",r_num,r_buf);
close(pipe_fd[READ]);
exit();
}
else if(pid>0) //父进程写
{
close(pipe_fd[READ]);
strcpy(w_buf,"hello world!n");
if(write(pipe_fd[WRITE],w_buf,strlen(w_buf))==-1)
printf("parent write overn ");
close(pipe_fd[WRITE]);
printf("parent close fd[WRITE] over n");
sleep(10);
}
}
/**************

* readtest.c *

**************/

#include
#include
#include

#define READ 0
#define WRITE 1

main()
{
int pipe_fd[2];
pid_t pid;
char r_buf[100];
char w_buf[32];
char* p_wbuf;
int r_num;
int cmd;
memset(r_buf,0,sizeof(r_buf));
memset(w_buf,0,sizeof(r_buf));
p_wbuf=w_buf;
if(pipe(pipe_fd)<0)
{
printf("pipe create error ");
return -1;
}

if((pid=fork())==0) //子进程读
{
close(pipe_fd[WRITE]);
sleep(3); //确保父进程关闭写端
r_num=read(pipe_fd[READ],r_buf,100);
printf( "read num is %d the data read from the pipe is %s n",r_num,r_buf);
close(pipe_fd[READ]);
exit();
}
else if(pid>0) //父进程写
{
close(pipe_fd[READ]);
strcpy(w_buf,"hello world!n");
if(write(pipe_fd[WRITE],w_buf,strlen(w_buf))==-1)
printf("parent write overn ");
close(pipe_fd[WRITE]);
printf("parent close fd[WRITE] over n");
sleep(10);
}
}

编译运行,看到预期结果

3.利用两个管道进行双向通信

(1)创建两个管道:管道1(父->子),管道2(子->父)

(2)fork()产生子进程

(3)父进程:close(fd1[READ]); close(fd2[WRITE]);

(4)子进程:close(fd1[WRITE]); close(fd2[READ]);

下面做一个练习,是利用双向通信实现父子进程协作把整数x从1加到10

view plaincopy to clipboardprint?
#include
#include
#include
#include
#include

#define MAXLINE 1024
#define READ 0
#define WRITE 1

main(void)
{
int x;
pid_t pid;
int pipe1[2],pipe2[2];
/*初始化管道*/
pipe(pipe1);
pipe(pipe2);

pid = fork();
if(pid < 0)
{
printf("create process error!n");
exit(1);
}
if(pid == 0) //子进程
{
close(pipe1[WRITE]);
close(pipe2[READ]);
do
{
read(pipe1[READ],&x,sizeof(int));
printf("child %d read: %dn",getpid(),x++);
write(pipe2[WRITE],&x,sizeof(int));
}while(x<=9);
//读写完成后,关闭管道
close(pipe1[READ]);
close(pipe2[WRITE]);
exit(0);
}
else if(pid > 0) //父进程
{
close(pipe2[WRITE]);
close(pipe1[READ]);
x = 1;
//每次循环向管道1 的1 端写入变量X 的值,并从
//管道2 的0 端读一整数写入X 再对X 加1,直到X 大于10
do{
write(pipe1[WRITE],&x,sizeof(int));
read(pipe2[READ],&x,sizeof(int));
printf("parent %d read: %dn",getpid(),x++);
}while(x<=9);
//读写完成后,关闭管道
close(pipe1[WRITE]);
close(pipe2[READ]);
waitpid(pid,NULL,0);
exit(0);
}
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/benny_cen/archive/2009/03/10/3976546.aspx

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24790158/viewspace-1041140/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/24790158/viewspace-1041140/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值