有名管道介绍及使用

有名管道简介:

  • 匿名管道,由于没有名字只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道(FIFO),也叫命名管道、FIFO文件。
  • 有名管道(FIFO)不同于匿名管道之处在于它提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,并且其打开方式和打开一个普通文件是一样的。这样即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问路径,就能够彼此通过FIFO相互通信。因此,通过FIFO,不相关的进程也能交换书就。
  • 一旦打开了FIFO,就能在它上面使用与操作匿名管道和其他文件的系统调用一样的I/O系统调用了(如read()\write()\close())。与管道一样,FIFO也有一个写入端和一个读取端并且从管道中读取数据的顺序与写入数据的顺序一致。
  • 有名管道(FIFO)和匿名管道(pipe)有一些特点是相同的,不一样的地方在于:
    1. FIFO文件系统中作为一个特殊文件存在,但FIFO中的内容却放在内存中。
    2. 当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便以后使用。
    3. FIFO有名字,不相关的进程可以通过打开有名管道进行通信。

有名管道的使用:

  • 通过命令创建有名管道

    mkfifo [name]  
    
  • 通过函数创建有名管道

#include <sys/types.h>
#include <sys/stat.h>

  int mkfifo(const char *pathname, mode_t mode);

  • 一旦使用mkfifo创建了一个FIFO,就可以使用open打开它。常见的文件I/O函数都可用于FIFO。
  • FIFO严格遵循先进先出(First in First out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。它不支持诸如lseek()等文件定位操作。
有名管道的注意事项:
        当只打开读端或者写端的时候,管道会产生阻塞,直到管道的另一端打开

    读管道:
        管道中有数据,read返回读到的字节数
        管道中无数据:
            管道写端被全部关闭,read返回0(相当于读到文件末尾)
            管道写端没有全部关闭,read阻塞等待

    写管道:
        管道读端被全部关闭,进行异常终止(收到一个SIGPIPE信号)
        管道读端没有被完全关闭:
            管道已经满了,write会阻塞
            管道没有写满,write将写入数据,返回写入的字节数

下面是关于没有亲缘关系的两个进程之间的通信简单案例:

//向管道中写数据

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


using std::cout;
using std::endl;


int main(){

    

    //判断文件是否存在
    int ext = access("test",F_OK);
    if(ext == -1){
        cout << "管道不存在,创建管道!" << endl;

        //如果不存在,创建管道
        int ret = mkfifo("test",0664);
    
        if(ret == -1){
            perror("mkfifo");
            exit(0);

        }
    }

    //打开管道,向管道里写入数据
    int fd = open("test",O_WRONLY);
    if(fd == -1){
        perror("open");
        exit(0);
    }
    char buf[1024];
    for(int i=0; i<20;++i){
        sprintf(buf,"hello, %d\n",i);
        write(fd,buf,strlen(buf));
        sleep(1);
    }

    close(fd);
    return 0;
}
//从管道中读数据


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


using std::cout;
using std::endl;

int main(){

    //打开管道文件
    int fd = open("test",O_RDONLY);
    if(fd == -1){
        perror("open");
        exit(0);
    }

    //读数据
    char buf[1024];
    while(1){

        int len = read(fd,buf,sizeof(buf));
        if(len == 0){
            cout << "写端关闭..."<<endl;
            break;
        }
        cout << "buf: "<<buf<<endl;
        memset(buf,0,1024);
    }
    
    close(fd);

    return 0;
}
posted @   nakejimamiyuki  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示