//基于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])操作,就会导致有消费者进程永远等待,无法返回。