一 Linux进程间通信( 四 )


命名管道读写操作以及注意事项一旦创建了一个FIFO,就可以用open打开它,常见的文件I/O都可以作用于FIFO文件 。
FIFO严格的遵循先进先出的原则,对管道以及FIFO的读总是从开始处返回数据,对它们的写则是把数据添加到末尾 。

  • 一个为只读而打开一个管道的进程会阻塞直到另外一个进程为只写打开该管道
  • 一个为只写而打开一个管道的进程会阻塞直到另外一个进程为只读打开该管道
读写规则:
读管道
  • 管道中有数据,read返回返回实际读到的字节数
  • 管道中无数据:(1)若管道写端被全部关闭,read返回0
?(2)若写端没有全部关闭,read阻塞等待
写管道
  • 管道读端全部被关闭,进程异常终止
  • 管道读端没有全部关闭:(1)若管道已经满了 。write阻塞
?(2)若管道没满,write将数据写入,并返回实际写入的字节数
使用命名管道进行通信接下来我会使用命名管道实现简单的版本聊天 。
一 Linux进程间通信

文章插图
talkA.c
#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<fcntl.h>//先读后写//以只读的方式打开管道1//以只写的方式打开管道2define SIZE 1024int main() {int fdr = -1;int fdw = -1;int ret = -1;char buf[SIZE];//以只读的方式打开管道1fdr = open("fifo1",O_RDONLY);if(-1==fdr){perror("open");return 1;}printf("以只读的方式打开管道1....\n");//以只写的方式打开管道2fdw = open("fifo2",O_WRONLY);if(-1==fdw){perror("open");return 1;}printf("以只写的方式打开管道2....\n");//循环读写while(1){//读管道1memset(buf,0,SIZE);ret = read(fdr,buf,SIZE);if(ret<=0){perror("read");break;}printf("read:%s\n",buf);//写管道2memset(buf,0,SIZE);fgets(buf,SIZE,stdin);//去掉最后一个换行符if('\n'==buf[strlen(buf)-1])buf[strlen(buf)-1]=0;//写管道ret = write(fdw,buf,strlen(buf));if(ret<=0){perror("write");break;}printf("write ret:%d\n",ret);}//关闭文件描述符close(fdr);close(fdw);}talkB.c
#include<stdio.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<fcntl.h>//以只读的方式打开管道2//以只写的方式打开管道1#define SIZE 1024int main(){int fdr = -1;int fdw = -1;int ret = -1;char buf[SIZE];//以只写的方式打开管道1fdw = open("fifo1",O_WRONLY);if(-1==fdw){perror("open");return 1;}printf("以只写的方式打开管道1....\n");//以只读的方式打开管道2fdr = open("fifo2",O_RDONLY);if(-1==fdr){perror("open");return 1;}printf("以只读的方式打开管道2....\n");//循环读写while(1){//写管道1memset(buf,0,SIZE);fgets(buf,SIZE,stdin);//去掉最后一个换行符if('\n'==buf[strlen(buf)-1])buf[strlen(buf)-1]=0;//写管道ret = write(fdw,buf,strlen(buf));if(ret<=0){perror("write");break;}printf("write ret:%d\n",ret);//读管道2memset(buf,0,SIZE);ret = read(fdr,buf,SIZE);if(ret<=0){perror("read");break;}printf("read:%s\n",buf);}//关闭文件描述符close(fdr);close(fdw);}运行结果如下:可以实现阻塞式的数据读取
一 Linux进程间通信

文章插图
当两个进程通信的时候,我们查看fifo的大小:
一 Linux进程间通信

文章插图
可以发现,管道的大小没有发生变化 。其实两个进程通信是在内存中进行的,并没有把数据写到管道中,因为管道只是一个符号性的文件 。如果是在管道写数据,那么IO次数会很多,效率太低了 。
【一 Linux进程间通信】

经验总结扩展阅读