linux命名管道:fifo

linux命名管道:fifo

一、命名管道

    除了创建方式,FIFO文件与管道极为相似。FIFO是非匿名的管道,通过系统调用mkfifo()存在于文件系统中。

二、FIFO相关函数

函数名称int mkfifo(const char *pathname, mode_t mode)
头文件<sys/types.h><sys/stat.h>
函数参数说明
pathname创建FIFO所用的路径名
mode指定FIFO的属性
返回值成功:0,失败:-1
函数名称int open(const char *pathname, int flags)
参数说明
头文件<sys/types.h><sys/stat.h><fcntl.h>
pathname打开的目标文件
flags打开方式
返回值成功:文件描述符,失败:-1

flags(必须为一下三个参数中的一个):
    O_RDONLY,O_WRONLY,O_RDWR

函数名称ssize_t read(int fd, void *buf, size_t count)
头文件<unistd.h>
参数说明
fd目标文件描述符
buf读取数据的缓存
count此次读取的最多字节数
返回值成功:此次读取的字节数,失败:-1
函数名称int stat(const char *path, sturct stat *buf)
头文件<sys/types.h><sys/stat.h><unistd.h>
参数说明
path指定要操作的目标文件路径
buf文件属性存储的结构体缓存地址
返回值成功:0,失败:-1
函数名称mode_t umask(mode_t mask)
头文件<sys/types.h><sys/stat.h>
参数说明
mask要替换的模式掩码
返回值原mask值
函数名称ssize_t write(int fd, const void *buf, size_t count)
头文件<unistd.h>
参数说明
fd操作的文件描述符
buf写入数据的缓存首地址
count此次写入数据的最大字节数
返回值成功:写入的字节数,失败:-1
函数名称int mkfifoat(int dirfd, const char *pathname, mode_t mode)
头文件<fcntl.h><sys/stat.h>
参数说明
dirfd目录文件描述符
pathname路径
mode创建模式
返回值成功:0,失败:-1

    与mkfifo()的异同:
      二者创建命名管道的方式是相同的;
      当pathname指定的路径为相对路径时,mkfifo()是以进程的工作路径为基础,而mkfifoat()以dirfd所引用的目录路径为基础路径来创建命名管道;
      当pathname指定的路径为绝对路径时,dirfd参数被忽略;
      在pathname为相对路径的情况下,若dirfd的值为AT_FDCWD,则pathname被解释为与进程的工作目录相对的相对路径(同mkfifo())。

三、相关介绍

  一个FIFO特殊文件(命名管道)与管道相似,不同的是FIFO是作为文件系统的一部分被访问的。它可以被多个进程进行读、写。当多个进程通过FIFO进行数据交换时,内核在内部进行数据传送,并不将数据写入文件系统。因此,FIFO文件在文件系统中没有任何内容。FIFO在文件系统中的访问入口仅作为一个引用指针,使得各进程可以在文件系统中访问它。
  内核仅为每个被进程打开的FIFO维持一个实例,且只有双端(读端、写端)都被打开时才可以进行数据传输。通常情况下,打开一个FIFO会阻塞至对端也被打开。
  进程可通过非阻塞方式打开一个FIFO。在此情况下,以只读方式打开的一端将会成功,以只写打开的一端将会失败,并返回ENXIO(没有此设备或地址),除非对端(即读端)早已被打开。
  在linux下,以阻塞或非阻塞的方式打开一个FIFO进行读或写都会成功。POSIX将此视为未定义行为。当同一线程同时使用读、写端与自身进行通信时,需要十分小心地避免死锁。

四、测试代码

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

#include<iostream>

int main()
{
    mode_t mode = S_IWOTH | S_IROTH;
    if(-1 == mkfifo("./namedpipe", mode))
    {
        perror("Mkfifo:");
        return -1;
    }
    pid_t p_id = fork();
    if(0 > p_id)
    {
        perror("Precess Creation:");
        return -1;
    }
    if(0 == p_id)
    {
        //父进程;
        int r_end = open("./namedpipe", O_RDONLY);
        std::cout << " Open the read end of the fifo. " << std::endl;
        if(-1 == r_end)
        {
            std::cout << __LINE__ << " ";
            perror("Open namedpipe:");
            return -1;
        }
        char buf[1024] = {0x00};
        ssize_t r_bytes = 0;
        size_t l_bytes = 0;
        while(true)
        {
            memset(buf, 0x00, sizeof(buf));
            r_bytes = read(r_end, buf, sizeof(buf));
            if(-1 == r_bytes)
            {
                std::cout << __LINE__ << " ";
                perror("Read end:");
            }
            if(0 < r_bytes)
            {
                std::cout << "Recv data: " << buf << std::endl;
            }
        }
    }
    else 
    {
        //子进程:写端
        int w_end = open("./namedpipe", O_WRONLY);
        if(-1 == w_end)
        {
            std::cout << __LINE__ << " ";
            perror("Open named fifo of w_end: ");
            return -1;
        }
        ssize_t w_bytes = 0;
        char buf[1024] = "Hello parent precess, I am greet to you by a fifo data dealer.";
        int loop_cnt = 5;
        while (loop_cnt--)
        {
            sleep(3);
            w_bytes = write(w_end, buf, strlen(buf));
            if(-1 == w_bytes)
            {
                std::cout << __LINE__ << " ";
                perror("Write data: ");
            }
        } 
        return 0;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值