#include "sys/types.h" #include "sys/file.h" #include "unistd.h" 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){ if(pipe(pipe_fd)<0){//传输出错 printf("pipe create error \n"); exit(-1); } else{ printf("pipe is created successfully!\n"); //谁占用管道谁进行数据传输 if((pid1=fork())==0) producer(1); 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(0); } //生产者 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) //生产者1 strcpy(w_buf,"aaa\0"); else //生产者2 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(" producer %d is running!\n",id); if (id==1) //消费者1 strcpy(w_buf,"ccc\0"); else //消费者2 strcpy(w_buf,"ddd\0"); while(1){ sleep(1); strcpy(r_buf,"eee\0"); 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); }
时间: 2023-07-15 16:10:50 浏览: 74
这段代码实现了一个生产者-消费者模型,使用了管道进行进程间通信。具体流程如下:
1. 创建管道
使用pipe函数创建一个管道,返回两个文件描述符,分别代表管道的读和写端。
2. 创建进程
使用fork函数创建4个子进程,其中2个子进程作为生产者,另外2个子进程作为消费者。
3. 生产者进程
生产者进程通过管道的写端向管道中写入数据。每个生产者进程循环10次,每次向管道中写入一个字符串"aaa"或"bbb",并休眠3秒。
4. 消费者进程
消费者进程通过管道的读端从管道中读取数据。每个消费者进程循环读取管道中的数据,并打印出来。同时,每个消费者进程会向管道写入一个字符串"ccc"或"ddd",用于测试管道是否可靠地传输数据。
5. 关闭文件描述符
在主进程中,需要关闭管道的读和写端文件描述符,否则会有读者或者写者永远等待。
6. 等待子进程结束
使用wait函数等待所有子进程结束,然后退出程序。
相关问题
例 2:命名管道通信实例 分别编写读写进程的程序 write.c 和 read.c,两个程序之一在当前目录下创建一个 命名管道“mypipe”,然后 write 向管道写数据,read 从管道读数据,两个进程可 任意顺序运行。 编写 write.c: //write.c #include<stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <error.h> #include <fcntl.h> #include <unistd.h> #define N 256 int main(){ char buf[N]; int fd= open("./mypipe",O_WRONLY|O_CREAT,0666); if(fd!=-1) { printf("FIFO file is opened\n"); } else { perror("open failed"); exit(0); } printf("please input string\n"); scanf("%s",buf); getchar(); if ( write(fd,buf,sizeof(buf))!=-1 ) printf("write successful\n"); else perror("write failed:"); exit(EXIT_SUCCESS); } 编写 read.c: //read.c #include<stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <error.h> #include <fcntl.h> #include <unistd.h> #define N 256 int main(){ int fd= open("./mypipe",O_RDONLY|O_CREAT,0666); char buf[N]; if(fd!=-1) { printf("FIFO file is opened\n"); } else { perror("open failed"); exit(0); } if ( read(fd,buf,N )!=-1 ) printf("I received data %s\n",buf); else perror("read error:"); exit(EXIT_SUCCESS); } 运行方式:打开 2 个终端,分别运行读写进程。 请完成以下练习与回答问题: 练习 1:改写本例,使得写进程可以不断的向管道文件写,读进程可以不断的读, 思考如何控制读写顺序。 练习 2:本例中用于管道通信的是一个普通文件,请用 mkfifo 命令或 mkfifo( )函 数创建一个标准管道文件改写本例,查看一下通过管道文件不断读写有什么不同? 问题 1:请说明匿名管道与命名管道在创建方式上有何不同?为什么说匿名管道 只能用于有亲缘关系的进程间进行通信?
练习 1:
可以在写进程和读进程中都用 while 循环,不断地读写数据。为了控制读写顺序,可以在读进程中使用 sleep() 函数来暂停一段时间,等待写进程写入数据。
练习 2:
可以使用 mkfifo() 函数创建一个标准管道文件,具体操作可以参考以下代码:
```c
mkfifo("mypipe", 0666);
```
使用标准管道文件和命名管道文件进行通信的方式是一样的,不同的只是创建方式。通过标准管道文件进行通信时,需要先手动创建管道文件,而命名管道则可以在程序中动态创建。
问题 1:
匿名管道和命名管道在创建方式上的不同在于,匿名管道需要通过 pipe() 函数创建,而命名管道需要通过 mkfifo() 函数创建。
匿名管道只能用于有亲缘关系的进程间进行通信,因为它只能在创建它的进程及其子进程之间使用。而命名管道则可以被多个进程共享使用,因为它是通过文件系统中的文件来实现的。
/* madplay.c */ #include<stdlib.h> #include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include <sys/ioctl.h> #include<fcntl.h> #include<unistd.h> #include<linux/soundcard.h> #define MAXLINE 4096 #define SIZE 16 /* 量化位数 */ #define CHANNELS 1 /* 声道数目 */ #define rate 8000 void madplay(FILE *de_fp) { int fd = open("/dev/dsp", O_WRONLY); if (fd==-1) { perror("open of /dev/dsp failed"); exit(1); } int arg; int status; /* 设置采样时的量化位数 */ arg = SIZE; status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_BITS ioctl failed"); if (arg != SIZE) perror("unable to set sample size"); /* 设置采样时的声道数目 */ arg = CHANNELS; status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_CHANNELS ioctl failed"); if (arg != CHANNELS) perror("unable to set number of channels"); /* 设置采样时的采样频率 */ arg = rate; status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); if (status == -1) perror("SOUND_PCM_WRITE_WRITE ioctl failed"); unsigned char buf[MAXLINE]; printf("open of soundcard success\n");//test while(!feof(de_fp)){ printf("madplaying\n"); int status=fread(buf,sizeof(unsigned char),MAXLINE,de_fp);//de_fp文件数据读入buf if(status==0){ printf("status==0\n"); } else if (status != MAXLINE) perror("read wrong number of bytes"); write(fd,buf,status);//buf数据写入声卡 } close(fd); }优化代码
madplay.c 是一个程序文件的名称,它是一个用于播放MP3格式音频文件的开源软件。madplay.c 的实现基于mad音频解码器库,可以在 Linux、Unix、Windows 等操作系统中使用。其主要功能包括解码和播放 MP3 文件,支持循环、随机播放等操作。
阅读全文
相关推荐













