无名管道,由于没有名字,只能用于亲缘关系的进程间通信.。为了克服这个缺点,提出了有名管道(FIFO)。
FIFO不同于无名管道之处在于它提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信,因此,通过FIFO不相关的进程也能交换数据。值的注意的是,FIFO严格遵循先进先出(first in firstout),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它们不支持诸如Lseek()等文件定位操作。有名管道的名字存在于文件系统中,内容存放在内存中。有名管道比无名管道多了一个打开操作:open
FIFO的打开规则:
如果当前打开操作时为读而打开FIFO时,若已经有相应进程为写而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞到有相应进程为写而打开该FIFO(当前打开操作设置了阻塞标志);或者,成功返回(当前打开操作没有设置阻塞标志)。
如果当前打开操作时为写而打开FIFO时,如果已经有相应进程为读而打开该FIFO,则当前打开操作将成功返回;否则,可能阻塞直到有相应进程为读而打开该FIFO(当前打开操作设置了阻塞标志);或者,返回ENIO错误(当期打开操作没有设置阻塞标志)。
1、 实验步骤演示
(1):首先在一个终端中编译写端然后运行。
可见进程无法继续执行下去,此时打开另一个终端,编译读过程并运行,显示如下:
而且在读终端执行显示结果的同时,执行写进程的终端显示也发生了变化。可见读写进程需要同时进行才可以完成有名管道的通信。
写端代码: #include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include<fcntl.h> #include<limits.h> #include<sys/types.h> #include<sys/stat.h> #define FIFO_NAME "/home/owen/myfifo/my_fifo" // int main(int argc,char *argv[]) { int pipe_fd; int res; char buffer[]="Hello world!"; if(access(FIFO_NAME,F_OK)==-1) //file exist { res=mkfifo(FIFO_NAME,0766); if(res!=0) { fprintf(stderr,"Could not creat fifo %s\n",FIFO_NAME); exit(1); } } printf("Process %d opening FIFO O_WRONLY\n",getpid()); pipe_fd=open(FIFO_NAME,O_WRONLY); printf("the file`s descriptor is %d\n",pipe_fd); if(pipe_fd!=-1) { res=write(pipe_fd,buffer,sizeof(buffer)); // write data printf("write data is %s,%d bytes is writen\n",buffer,res); (void)close(pipe_fd); //close } else exit(1); printf("Process %d finished\n",getpid()); exit(1); } 读端代码: #include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include<fcntl.h> #include<limits.h> #include<sys/types.h> #include<sys/stat.h> #define FIFO_NAME "/home/owen/myfifo/my_fifo" int main(int argc,char *argv[]) { int pipe_fd; int res; char buffer[4096]; int bytes_read=0; memset(buffer,'\0',sizeof(buffer)); printf("Process %d opening FIFO O_RDONLY\n",getpid()); pipe_fd=open(FIFO_NAME,O_RDONLY); printf("the file`s descriptor is %d\n",pipe_fd); if(pipe_fd!=-1) { bytes_read=read(pipe_fd,buffer,sizeof(buffer)); printf("the read data is %s\n",buffer); close(pipe_fd); //close } else exit(1); printf("Process %d finished,%d bytes read\n",getpid(),bytes_read); exit(1); }