10-进程间通信-有名管道FIFO(功能:传输数据)

时间:2022-09-05 15:08:38

一,有名管道概述:

有名管道也被称为FIFO文件,是一种特殊的文件。由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一,如使用

open,read,write等操作文件的方法对有名管道进行操作。

二、有名管道特点:

  1. 使不相关的两个进程彼此通信:a. 通过路径名指出,在文件系统中可见;  
                   b. 管道建立后,两进程可按普通文件一样对其操作。
  2. FIFO遵循先进先出规则:a. 对管道读从开始处返回数据;
                 b. 对管道写则把数据添加到末尾;
                 c. 不支持如lseek()等文件定位操作;

三、FIFO文件与普通文件的区别:

 FIFO文件在使用上和普通文件有相似之处,但是也有不同之处:
    1. 读取Fifo文件的进程只能以”RDONLY”方式打开fifo文件;
    2. 写Fifo文件的进程只能以”WRONLY”方式打开fifo文件;
    3. Fifo文件里面的内容被读取后,就消失了。但是普通文件里面的内容读取后还存在。 

三、操作有名管道的函数:

  1. 创建有名管道:mkfifo() 【其实就是创建fifo文件,要对这个fifo文件操作就跟普通文件一样】

    创建有名管道FIFO:mkfifo()
    函数原型: int mkfifo(const char *pathname, mode_t mode);
    头文件: 《sys/types.h》《sys/stat.h》
    功能: 创建一个fifo文件(有名管道);
    参数: pathname:创建fifo文件的名字;

    mode:访问fifo文件的权限;

    返回值: 成功:返回0;

    失败:返回-1;

  2. 删除有名管道:

    删除有名管道FIFO:unlink()
    函数原型: int unlink(const char *pathname);
    头文件: 《unistd.h》
    功能: 主要意思是从文件系统中删除一个指定名字的文件,并清空这个文件使用的可用的系统资源,如空间、进程等
    参数: pathname:删除mkfifo函数创建fifo文件的名字
    返回值: 成功:返回0;失败:返回-1。

  3. 创建管道成功后,可使用open()、read()和write()等函数。
      为读而打开的管道可在open()中设置O_RDONLY
      为写而打开的管道可在open()中设置O_WRONLY

  4. 与普通文件不同的是阻塞问题
      •普通文件的读写时不会出现阻塞问题
      •在管道的读写中却有阻塞的可能,
      •fifo文件读取后内容就不存在了。
      •非阻塞标志:在open()函数中设定为O_NONBLOCK

  5. 阻塞打开与非阻塞打开

    1. 对于读进程
        •若该管道是阻塞打开,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入
        •若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,则读函数将立刻返回0
    2. 对于写进程
        •若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入
        •若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败

四、示例:

写两个程序,一个读fifo文件,一个读fifo文件。

//write
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

void main(void) {
        int fd = mkfifo("/home/nan/test/god",0666) ;
        fd = open( "/home/nan/test/god",O_WRONLY ) ;
        write( fd , "write" , 6 ) ;
        close(fd) ;
}
//read
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

void main() {
        int fd = open( "/home/nan/test/god",O_RDONLY ) ;
        char buf[6] ;
        read( fd , buf , 6 ) ;
        printf( "read is : %s\n",buf ) ;
        close(fd);
        unlink( "/home/nan/test/god" ) ;
}
先写进程启动后,处于阻塞状态,除非读进程启动读取后。