【UNIX网络编程】FIFO
来源:互联网 发布:淘宝达人怎么发布单品 编辑:程序博客网 时间:2024/06/07 04:47
管道作为进程间通信的最古老方式,它的缺点是没有名字,因此只能用在有亲缘关系的父子进程之间。对于无亲缘关系的进程间,无法用管道进行通信。FIFO可以完成无亲缘关系的进程间的通信,FIFO也被称为命名管道。它是一种特殊类型的文件,在文件系统中以文件名的形式存在,但它的行为却和上面提到的管道类似。
创建命名管道有两种方法:
1、在命令行上执行命令:mkfifo filename 来创建FIFO。
2、使用mkfifo函数创建FIFO。
#include <sys/stat.h>#include <sys/types.h>int mkfifo(const char *pathname, mode_t mode); //返回值:若成功则返回0,若出错则返回-1
注意,mkfifo函数只是创建FIFO,要想打开它,还必须使用open函数,而且创建的过程中是隐含了O_CREAT| O_EXCL标志的,也就是说它要么创建一个新的FIFO,要么返回一个EEXIST错误。如果不希望创建一个新的FIFO,就改调用open而不是mkfifo。要打开一个已存在的FIFO或创建一个新的FIFO,应先调用mkfifo,再检查它是否返回EEXIST错误,若返回该错误则改为调用open。FIFO不能打来来既读又写,因为它是半双工的。
FIFO与管道的区别主要有以下两点:
1、创建并打开一个管道只需要调用pipe。创建并打开一个FIFO则需要调用mkfifo后再调用open。
2、管道在所有进程最终都关闭它之后自动消失。FIFO的名字则只有调用unlink才从文件系统中删除。
管道与FIFO都有系统加在他们上面的限制:
1、OPEN_MAX 一个进程在任意时刻打开的最大描述符数。
2、PIPE_BUF 可原子地写一个管道或FIFO的最大数据量。
下面就以例子来学习FIFO的创建、访问、打开等操作。
创建方法一mkfifo命令:
book@book-desktop:/work/tmp/unp$ mkfifo my_file //利用mkfifo命令创建my_file命名管道book@book-desktop:/work/tmp/unp$ ls -l my_file prw-r--r-- 1 book book 0 2014-07-03 15:44 my_file//利用ls命令查看上一条命令创建的my_file命名管道book@book-desktop:/work/tmp/unp$ mkfifo my_filemkfifo: cannot create fifo `my_file': File exists//因为命名管道已经存在,所以此时的mkfifo命令失败
创建方法二mkfifo函数:
将上面的命名管道删除后,利用下面的语句重新创建my_file命名管道。
int res = mkfifo("my_file", 0777);if(res == 0)printf("FIFO created\n");exit(EXIT_SUCCESS);
查看结果如下:
book@book-desktop:/work/tmp/unp$ rm -rf my_file book@book-desktop:/work/tmp/unp$ lsa.out fifo.c mutex pipemesg unpv22efifo fifocliserv pipe pxmsg unpv22e.tar.gzbook@book-desktop:/work/tmp/unp$ ./a.out FIFO createdbook@book-desktop:/work/tmp/unp$
访问上面创建的FIFO:
cat < my_file,因为此时FIFO里没有任何数据,所以此时阻塞。
echo "Hello world." > my_file,因为没有echo等待其他进程读取数据,所以同样阻塞。
使用open打开FIFO文件:
1、打开FIFO的主要限制是,程序不能以O_RDWR模式打开FIFO文件进行读写操作,因为通常我们只是单向传递数据。如果需要双向传递数据,就要创建一对FIFO。实现实例请参考之前写的客户-服务器程序,点此进入。
2、打开FIFO文件和打开普通文件的另一个区别是,对open_flag的O_NOBLOCK选项的用法。使用这个选项不仅改变open调用的处理方式,还会改变对这次open调用返回的文件描述符进行的读写请求的处理方式。
a、open(const char *path, O_RDONLY);这种情况下,open调用将阻塞,除非有一个进程以写方式打开同一个FIFO,否则不会返回。例如上面的cat命令的例子。
b、open(const char *path,O_RDONLY | O_NONBLOCK);即使没有其他进程以写方式打开FIFO,这个open调用也将成功立即返回。
c、open(const char *path, O_WRONLY); open调用将阻塞,知道有一个进程以读的方式打开同一个FIFO为止。如上面的echo命令的例子。
d、open(const char *path, O_WRONLY | O_NONBLOCK);函数立即返回,但如果没有进程以读方式打开FIFO,open调用将返回一个错误并且FIFO也不会被打开。
示例代码:
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO_NAME "my_file"int main(int argc, char **argv){int res;int open_mode = 0;int i;if(argc < 2){fprintf(stderr, "Usage : %s <some combinations of\O_RDONLY O_WRONLY O_NONBLOCK>\n", *argv);exit(EXIT_FAILURE);}for(i = 1; i < argc; i++){if(strncmp(*++argv , "O_RDONLY", 8) == 0);open_mode |= O_RDONLY;if(strncmp(*++argv , "O_WRONLY", 8) == 0);open_mode |= O_WRONLY;if(strncmp(*++argv , "O_NONBLOCK", 10) == 0);open_mode |= O_NONBLOCK;}if(access(FIFO_NAME, F_OK) == -1){res = mkfifo(FIFO_NAME, 0777);if(res != 0){fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);exit(EXIT_FAILURE);}}printf("Process %d opending FIFO\n", getpid());res = open(FIFO_NAME, open_mode);printf("Process %d result %d\n", getpid(), res);sleep(5);if(res != -1)close(res);printf("Process %d finished\n", getpid());exit(EXIT_SUCCESS);}对于FIFO的高级一点的应用,比如客户-服务器程序,进程间通信等,参见直接的总结,点此链接。
参考:
1、之前的总结:http://blog.csdn.net/to_be_it_1/article/details/28384117
- 【UNIX网络编程】FIFO
- unix网络编程----------fifo
- UNIX网络编程之管道与FIFO
- UNIX网络编程之管道与FIFO
- 《UNIX网络编程 卷2》 笔记: FIFO
- UNIX网络编程卷二 笔记 管道和FIFO
- unix网络编程卷2:管道和FIFO
- 《UNIX网络编程 卷2》 笔记: 使用FIFO实现信号量
- unix下fifo编程实践
- 网络编程之FIFO
- UNIX编程——管道和FIFO
- UNIX网络编程
- UNIX网络编程
- 关于Unix网络编程
- unix网络编程
- UNIX网络编程
- UNIX网络编程
- UNIX网络编程
- c语言位域
- 如何将Vim打造成一个成熟的IDE
- ACM从零开始---电子科大POJ "整数的千位分隔"
- Linux mysql停止失败的解决办法 Stopping MySQL database server mysqld [fail]
- 牛顿迭代法
- 【UNIX网络编程】FIFO
- java基础
- BCM芯片FP原理及相关SDK数据结构介绍
- java读取xml文件
- POJ-2393-Yogurt factory
- OOP 5大原则
- 【ios】论如何让 MWPhotoBrowser 动态显示 gif
- pygtk消息提示对话框
- HDU 4508 湫湫系列故事——减肥记I (2013腾讯编程马拉松初赛第一场)