博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux编程基础之进程间通信之二:有名管道
阅读量:4195 次
发布时间:2019-05-26

本文共 2749 字,大约阅读时间需要 9 分钟。

一、有名管道的简单说明

无名管道只能在具有亲缘关系的进程间通信,大大地限制了管道的使用。而有名管道的出现则突破了这种限制,它可以使任意两个进程间进行通信。该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。。不过值得注意的是,FIFO 是严格地遵循先进先出规则的,对管道及FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如lseek()等文件定位操作。

有名管道的创建可以使用函数mkfifo(),该函数类似文件中的open()操作,可以指定管道的路径和打开的模式。在创建管道成功之后,就可以使用open()、read()和write()这些函数了。与普通文件的开发设置一样,对于为读而打开的管道可在open()中设置O_RDONLY,对于为写而打开的管道可在open()中设置O_WRONLY,在这里与普通文件不同的是阻塞问题。由于普通文件的读写时不会出现阻塞问题,而在管道的读写中却有阻塞的可能,这里的非阻塞标志可以在open()函数中设定为O_NONBLOCK。下面分别对阻塞打开和非阻塞打开的读写进行讨论。

(1)对于读进程

  • 若该管道是阻塞打开,且当前FIFO 内没有数据,则对读进程而言将一直阻塞到有数据写入。
  • 若该管道是非阻塞打开,则不论FIFO 内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0。
(2)对于写进程

  • 若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。
  • 若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败。

二、有名管道的创建函数

管道创建函数如下所示:

int mkfifo(const char *filename,mode_t mode)
        filename:要创建的管道

        mode :  O_RDONLY,读管道

                      O_WRONLY,写管道

                      O_RDWR,读写管道

                      O_NONBLOCK:非阻塞

                      O_CREAT:如果该文件不存在,那么就创建一个新的文件,并用第三个参数为其设置权限

                      O_EXCL:如果使用O_CREAT 时文件存在,那么可返回错误消息。这一参数可测试文件是否存在

        返回值:0成功,其他返回错误代码

操作中经常会出现以下错误如下表所示(方便出错查询):

三、测试

编写一个实例进行测试:需要编写两个独立进程,一个进程用来读取传入的数据,一个进程用来写入数据;在读进程当中首先创建的fifo文件,然后打开并不停的读取FIFO文件当中的内容,在写进程当中打开FIFO文件然后向FIFO文件当中写入相应的内容。具体如下:

读端:

#include 
#include
#include
#include
#include
#include
#define FIFO_NAME "yl_fifo" // 定义FIFO文件的名称#define BUFFER_SIZE 256 // 定义缓冲区的大小/* 创建FIFO文件,并以阻塞方式读取FIFO文件当中的内容 * */int main(void){ int ret; int fd; char buf[BUFFER_SIZE]; int buflen; /* 创建FIFO文件 */ if(-1 == access(FIFO_NAME, F_OK)) // 判断FIFO文件是否存在 { ret = mkfifo(FIFO_NAME, 0666); // 以可读可写方式创建一个FIFO文件 if(-1 == ret) { printf("mkfifo error!\n"); return -1; } } fd = open(FIFO_NAME, O_RDONLY); // 打开这个文件 if(-1 == fd) { printf("open error!\n"); return -1; } /* 以阻塞的方式读取文件当中的内容 */ while(1) { memset(buf, 0, BUFFER_SIZE); buflen = read(fd, buf, BUFFER_SIZE); if(buflen > 0) { buf[buflen] = '\0'; if(!strcmp("quit", buf)) // 如果读到的信息是quit,则退出 { return 0; } else // 将读取的信息打印出来 { printf("Read from fifo : %s\n", buf); } } } close(fd); // 关闭这个文件 return 0;}
写端:

#include 
#include
#include
#include
#include
#include
#define FIFO_NAME "yl_fifo" // 定义FIFO文件的名称#define BUFFER_SIZE 256 // 定义缓冲区的大小/* 向FIFO文件当中写入信息 * usage : fifo_write
*/int main(int argc, char *argv[]){ int fd; char buf[BUFFER_SIZE]; int buflen; if(2 != argc) { printf("usage : %s
\n", argv[0]); return -1; } fd = open(FIFO_NAME, O_WRONLY); // 打开这个文件 if(-1 == fd) { printf("open error!\n"); return -1; } /* 将消息写入FIFO文件当中 */ sprintf(buf, "%s", argv[1]); buflen = write(fd, buf, BUFFER_SIZE); if(buflen <= 0) { printf("write error!\n"); return -1; } else { printf("Write to fifo : %s\n", buf); } close(fd); // 关闭这个文件 return 0;}
对读端和写端分别进行编译和运行如下所示:

你可能感兴趣的文章
C#入门学习笔记(二):数据类型与表达式
查看>>
解决旧版Animation无法在新版动画animator中播放问题
查看>>
U3D人物选择界面:rawimage与摄像机
查看>>
如何做一名游戏测试?
查看>>
腾讯物联网操作系统TencentOS tiny线上移植大赛,王者机器人、QQ公仔、定制开发板等礼品等你来拿 !
查看>>
为云而生,腾讯云服务器操作系统TencentOS内核正式开源
查看>>
腾讯汤道生:开源已成为许多技术驱动型产业重要的创新推动力
查看>>
微信小程序多端框架 kbone 开源
查看>>
视频质量评估算法 DVQA 正式开源
查看>>
腾讯优图开源视频动作检测算法DBG,打破两项世界纪录
查看>>
在中国提供了60亿次服务的疫情模块向世界开源 腾讯抗疫科技输出海外
查看>>
在中国提供了60亿次服务的疫情模块向世界开源
查看>>
世界卫生组织与腾讯加深合作 新冠肺炎AI自查助手全球开源
查看>>
Hibernate 中get, load 区别
查看>>
java反射详解
查看>>
JPA 注解
查看>>
JQuery 简介
查看>>
Java创建对象的方法
查看>>
Extjs自定义组件
查看>>
TreeGrid 异步加载节点
查看>>