一、进程管道
1.读管道
(1)代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
FILE *read_fp;
char buffer[BUFSIZ+1];
int chars_read;
memset(buffer,‘\0’,sizeof(buffer));
read_fp=popen(“uname -a”,“r”);
if(read_fp!=NULL){
chars_read=fread(buffer,sizeof(char),BUFSIZ,read_fp);
if(chars_read>0) printf(“Output was:-\n%s\n”,buffer);
pclose(read_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
(2)运行结果:
2.写管道
(1)代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
FILE *write_fp; //文件流指针
char buffer[BUFSIZ+1]; //缓冲区
sprintf(buffer,"Once upon a time, there was...\n");
write_fp=popen("wc -w","w");
if(write_fp!=NULL){
fwrite(buffer,sizeof(char),strlen(buffer),write_fp);
pclose(write_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
(2)运行结果:
二、匿名管道
通过 pipe 函数创建匿名管道,在两个进程间传递数据,而不需要启动一个 shell 来解释请求的命令。该管道工作在更底层,访问管道,使用文件描述符而不是文件流,所以使用系统调用 read 和 write 来访问管道数据。
1.生产者/消费者的管道模型
(1)代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
int data_processed;
int file_pipes[2];
const char some_data[]="123";
char buffer[BUFSIZ+1]; //缓冲区
memset(buffer,'\0',sizeof(buffer)); //初始化缓冲区
if(pipe(file_pipes)==0){
data_processed= write(file_pipes[1],some_data,strlen(some_data));
printf("Wrote %d bytes\n",data_processed);
data_processed=read(file_pipes[0],buffer,BUFSIZ);
printf("Read %d bytes: %s\n",data_processed,buffer);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
(2)运行结果:
2.父子进程通过管道通信
(1)代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
int data_processed;
int file_pipes[2];
const char some_data[]="123";
char buffer[BUFSIZ+1];
pid_t pid;
memset(buffer,'\0',sizeof(buffer));
if(pipe(file_pipes)==0){ //同上
pid=fork(); //创建子进程
if(pid == -1){
fprintf(stderr,"Fork failure");
exit(EXIT_FAILURE);
}
if(pid==0){ //子进程并发执行
data_processed=read(file_pipes[0],buffer, BUFSIZ); //读管道
printf("Read %d bytes: %s\n", data_processed,buffer);
exit(EXIT_SUCCESS);
}
else{ //父进程并发执行
data_processed=write(file_pipes[1], some_data, strlen(some_data));
printf("Wrote %d bytes\n",data_processed);
}
}
exit(EXIT_SUCCESS);
}
(2)运行结果:
3.利用信号量实现父子同步通信
(1)代码:
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
void err_printf(char *p)
{
printf("%s\n",p);
exit(0);
}
int main(void)
{
int fd1[2],fd2[2];
pid_t pid;
char *str="the data from parent process.\n";
char *dtr="the data from child process.\n";
char buf[1024];
if(pipe(fd1)<0)
err_printf("pipe fd1 fail");
if(pipe(fd2)<0)
err_printf("pipe fd2 fail");
if((pid=fork())<0)
err_printf("fork fail");
else if(pid==0)
{
close(fd1[1]);
close(fd2[0]);
//子进程读取数据
int num=read(fd1[0],buf,sizeof(buf));
//在终端打印
write(STDOUT_FILENO,buf,num);
puts("child recevied the parent message\n");
//子进程向父进程写东西
write(fd2[1],dtr,strlen(dtr)+1);
}
else
{
close(fd1[0]);
close(fd2[1]);
write(fd1[1],str,strlen(str)+1);
int num=read(fd2[0],buf,sizeof(buf));
puts("parent recevied the child message\n");
write(STDOUT_FILENO,buf,num);
}
exit(0);
return 0;
}
(2)运行结果:
三、命名管道 FIFO(常用在不相关进程间交换数据)
1.shell 命令创建命名管道:$ mkfifo /tmp/my_fifo
查看命名管道命令:$ ls –lF /tmp/my_fifo
2. 程序创建命名管道
(1)代码:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc,char *argv[]){
int res = mkfifo("/tmp/my_fifo",0777); //创建一个命名管道
if(res==0) //创建成功则打印输出
printf("FIFO created\n");
exit(EXIT_SUCCESS);
}
(2)运行结果:
3.访问命名管道
(1))消费者
读空 FIFO 文件:$cat < /tmp/my_fifo
(2)生产者
向 FIFO 写数据(必须另外开一个终端执行如下命令)
$ echo “Hello,world” > /tmp/my_fifo