zoukankan      html  css  js  c++  java
  • 【UNIX网络编程】FIFO

    管道作为进程间通信的最古老方式,它的缺点是没有名字,因此仅仅能用在有亲缘关系的父子进程之间。对于无亲缘关系的进程间。无法用管道进行通信。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_file
    mkfifo: cannot create fifo `my_file': File exists	//由于命名管道已经存在,所以此时的mkfifo命令失败

    创建方法二mkfifo函数:

    将上面的命名管道删除后,利用以下的语句又一次创建my_file命名管道。

    	int res = mkfifo("my_file", 0777);
    	if(res == 0)	printf("FIFO created
    ");
    	exit(EXIT_SUCCESS);

    查看结果例如以下:

    book@book-desktop:/work/tmp/unp$ rm -rf my_file 
    book@book-desktop:/work/tmp/unp$ ls
    a.out  fifo.c       mutex  pipemesg  unpv22e
    fifo   fifocliserv  pipe   pxmsg     unpv22e.tar.gz
    book@book-desktop:/work/tmp/unp$ ./a.out 
    FIFO created
    book@book-desktop:/work/tmp/unp$ 

    訪问上面创建的FIFO:

    cat < my_file,由于此时FIFO里没有不论什么数据。所以此时堵塞。

    echo "Hello world." > my_file,由于没有echo等待其它进程读取数据。所以相同堵塞。


    使用open打开FIFO文件:

    1、打开FIFO的主要限制是,程序不能以O_RDWR模式打开FIFO文件进行读写操作,由于通常我们仅仅是单向传递数据。假设须要双向传递数据,就要创建一对FIFO。

    实现实例请參考之前写的客户-server程序,点此进入

    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>
    ", *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
    ", FIFO_NAME);	
    			exit(EXIT_FAILURE);
    		}
    	}
    
    	printf("Process %d opending FIFO
    ", getpid());
    	res = open(FIFO_NAME, open_mode);
    	printf("Process %d result %d
    ", getpid(), res);
    	sleep(5);
    	if(res != -1)	close(res);
    	printf("Process %d finished
    ", getpid());
    	exit(EXIT_SUCCESS);
    }
    对于FIFO的高级一点的应用。比方客户-server程序,进程间通信等,參见直接的总结,点此链接

    參考:

    1、之前的总结:http://blog.csdn.net/to_be_it_1/article/details/28384117

    2、《Linux程序设计》 Neil Matthew&&Richard Stones
    3、《UNIX环境高级编程》Richard Stevenson
    4、《UNIX网络编程 卷2》 Richard Stevenson




  • 相关阅读:
    SQL 连接
    nvl() 数值替换函数 oracle使用
    Oracle 中sql语句中的取前n条数据
    设置序列
    Oracle创建用户 创建表空间 分配权限
    oracle11 刚刚安装后提示invalid username password logon denied
    关于index 索引
    事物
    数据库 oracle 设计三范式
    TXT编写程序-编译-执行流程
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6771049.html
Copyright © 2011-2022 走看看