linux管道生产大于消费,Linux下用fork()派生的子进程通过pipe管道通讯的实例详解("生产者-消费者"问题)...

//基于fork()系统调用

//#include "sys/types.h"//包含pid_t等的声明

//#include "sys/file.h"

//#include "unistd.h"//包含pipe(),fork()等的声明

#include "stdlib.h"//包含exit(),pid_t等的声明

#include "string.h"//包含strcpy()等的声明

#include "stdio.h"//包含printf()等的声明

char r_buf[4];//管道读取缓冲

char w_buf[4];//管道写入缓冲

int pipe_fd[2];//管道读写文件指针

pid_t

pid1,pid2,pid3,pid4;//用于保存子进程号,此程序中并没有用到,只有一个简单的赋值

int producer(int id);//“生产者”

int consumer(int id);//“消费者”

int main(int argc,char **argv)

{

//pipe()成功返回,失败返回-1

if(pipe(pipe_fd)<0){//文件指针fd[0]和fd[1]分别用于管道文件的读和写

printf("Pipe create error.\n");

exit(-1);

}

else{

printf("Pipe is created successfully !\n");

if((pid1=fork())==0)

producer(1);//对于fork()得到的子进程,pid1=0,于是调用一个生产者,以下三句类似

if((pid2=fork())==0)

producer(2);

if((pid3=fork())==0)

consumer(1);

if((pid4=fork())==0)

consumer(2);

}

close(pipe_fd[0]);//去掉之后,对程序结果没有影响

close(pipe_fd[1]);//需要加上这句,否则会有读者永远等待

int i,pid,status;

for(i=0;i<4;i++)

pid = wait(&status);

//exit()函数要做的工作是退出处理函数(我认为,相当于return),然后清理I/O缓冲,最后调用exit系统调用

exit(0);//main函数中,exit(int ret)等同于return ret;

}

int producer(int id){

printf("Producer %d is running !\n",id);

close(pipe_fd[0]);//关读

int i = 0;

for(i=1;i<10;i++){

sleep(3);

if(id == 1)//生产者

strcpy(w_buf,"aaa\0");

else//生产者

strcpy(w_buf,"bbb\0");

if(write(pipe_fd[1],w_buf,4) == -1)//写管道

printf("Write to pipe error\n");

}

close(pipe_fd[1]);//关写

printf("Producer %d is over !\n",id);

exit(id);

}

int consumer(int id){

close(pipe_fd[1]);//关写

printf("Consumer %d is running !\n",id);

if(id == 1)//消费者

strcpy(w_buf,"ccc\0");

else//消费者

strcpy(w_buf,"ddd\0");

while(1){

sleep(1);//一个消费者读取管道后暂时挂起,给另一个消费者运行的机会

strcpy(r_buf,"eee\0");

//read()返回值为0表示到了文件结尾;返回-1表示读取过程有错误;一般情况返回读取的字节总数

if(read(pipe_fd[0],r_buf,4) ==

0)//如果写入端尚未写入数据,则读操作被阻塞,陷入等待,不能返回;直至写文件指针被关闭

break;

printf("Consumer %d get %s,while the w_buf is

%s\n",id,r_buf,w_buf);

}

close(pipe_fd[0]);

printf("Consumer %d is over !\n",id);

exit(id);

}

以上代码中,关闭读文件操作符pipe_fd[0]的操作不是必须的,去掉之后,不会影响程序的运行结果,但是为了管道操作的规范性,需要加上close(pipe_fd[0])的操作

由于只有当read函数读到管道文件的结尾(写文件操作结束,read函数返回0)时,消费者进程consumer才能退出死循环,并结束,因此如果少了关闭写文件操作符的close(pipe_fd[1])操作,就会导致有消费者进程永远等待,无法返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值