管道:管道分为无名管道(pipe)跟有名管道(fifo)
管道通信过程:
进程A向管道中写数据,进程B从管道中读数据。读,写操作都是以阻塞方式。
无名管道:
特点:
1.只能用于具有亲缘关系(父子进程/兄弟进程)进程间通信
2.只能以半双工方式通信,且读 写端固定
3.可以将管道看成一种特殊文件,对管道读写就像对普通文件读写一些,只是它是以阻塞方式读写的。无名管道在本质上是一块内存缓冲区
创建无名管道函数:
int pipe(int fd[2])
参数:
当创建成功,返回对管道读写文件描述符,fd[0]读文件描述符,fd[1]|写文件描述符
返回值:
成功: 返回 0
失败: 返回-1 设置errno
注意:在利用fork/vfork创建子进程之前,创建无名管道
原因:用pipe创建无名管道后返回对这个管道读写文件描述符fd[2],在fork后,操作系统会复制fd[2]给子进程,子进程也就拥有了对这个管道的读写操作。
这也是为什么无名管道只适用有血缘关系进程间通信。
//*******************************************************************************************************************************
子进程向管道中写数据,父进程读管道数据,并向终端输出:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<string.h> int main(int argc,char** argv) { int fd[2]; pid_t pid; int ret=pipe(fd);//创建无名管道 if(ret<0)//创建失败 { perror("pipe error\n"); exit(1); } pid=fork(); if(pid<0)//创建子进程失败 { perror("fork error\n"); close(fd[0]); close(fd[1]); exit(1); }else if(pid==0)//子进程返回 { close(fd[0]);//关闭读端文件描述符 char buff[1024]="this is pipe test"; write(fd[1],buff,strlen(buff)); close(fd[1]);//关闭写端文件描述符 }else//父进程返回 { close(fd[1]); char buff[1024]; int count=read(fd[0],buff,1024); if(count<0)//读管道数据失败 { perror("parent process read error\n"); close(fd[0]); exit(1); } buff[count]='\0'; printf("receive data %s\n",buff); close(fd[0]); } return 0; }
实验输出:
有名管道:
特点:
1.适用于任何两个进程间进行通信
2.半双工通信方式
创建有名管道函数:
int mkfifo(const char* pathname,mode_t mode);
参数:
pathname:有名管道的名字
mode:当管道不存在时,创建管道文件权限
返回值:
成功:返回0
失败:返回-1 设置errno
//******************************************************************************
fifo_w.c:对管道fifo写数据
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/stat.h> #include<fcntl.h> #include<sys/types.h> #include<string.h> int main(int argc,char** argv) { char buff[1024]; int ret=mkfifo("fifo",0666);//创建管道文件 if(ret<0)//失败 { perror("mkfifo error\n"); exit(1); } int fd=open("fifo",O_WRONLY);//打开管道文件 if(fd<0)//失败 { perror("open fifo error\n"); exit(1); } while(1) { printf("write data "); fgets(buff,1024,stdin);//从终端读取字符串 write(fd,buff,1024);//写入管道 if(strncmp(buff,"end",3)==0)//从终端输入end退出程序 break; } close(fd); return 0; }
fifo_r.c从管道读数据:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> int main(int argc,char** argv) { char buff[1024]; int ret; int fd=open("fifo",O_RDONLY);//打开管道文件 if(fd<0) { perror("open error\n"); exit(1); } while(1) { ret=read(fd,buff,1024);//读管道数据 if(ret==0)//写端关闭 break; buff[ret]='\0'; printf("read data %s",buff); } close(fd); return 0; }
实验输出:左边读管道数据 右边写管道数据