代码仓库:https://gitee.com/tgwTTT/linux-learning-dai/tree/master/fifotest

匿名管道:

1.只能用于具有血缘关系的进程进行进程间通信(常用于父子)

思考:如果两个进程不相关,改如何进行通信

如:进程a打开了一个文件a

进程b也打开了文件a

内核中,操作系统会不会打文件a在内存中加载两次

答案是:不会!!

这也为我们命名管道奠定基础,是在两个文件里面进行通信读取

命名管道(Named Pipe,也叫 FIFO):

是一种 以文件形式存在于文件系统中 的进程间通信(IPC)机制。与匿名管道只能用于 亲缘进程 不同,命名管道允许任意两个无亲缘关系的进程 通过约定好的路径交换数据。

这是linux中的一种特殊文件管道文件,他不需要将内存刷新到磁盘,只需要去打开读取

mkfifo:创建一个管道文件

int ret = mkfifo("/tmp/myfifo", 0666);
    if (ret == -1) perror("mkfifo");
    return 0;

打开规则与阻塞行为

open 模式行为说明
O_RDONLY阻塞直到有写端打开
O_WRONLY阻塞直到有读端打开
O_NONBLOCK立即返回,若无对应端则 open 失败(errno=ENXIO)
不能用 O_RDWR会读回自己写的数据,失去管道意义

下面是实现一个简单的管道通信的例子:

class IpcFifo
{
    public:
    IpcFifo(const std::string& path,const std::string &name)
    :_path(path),_name(name)
    {
        _fifoname=_path+"/"+_name;
        umask(0);
        //新建管道
        int n=mkfifo(_fifoname.c_str(),0666);
        if(n!=0){
        std::cerr<<"mkfifo error"<

上面的类主要是一个管道文件的创建和销毁

class FileOper
{
    public:
    FileOper(const std::string& path,const std::string &name)
     :_path(path),_name(name),_fd(-1)
     {
         _fifoname=_path+"/"+_name;
     }
     ~FileOper(){}
    void OpenForRead(){
         _fd=open(_fifoname.c_str(),O_RDONLY);
        if(_fd<0){
            std::cerr<<"open error"<0){
        std::cout<<"send sucessful"<0){
            std::cout<<"client say "<0){
            close(_fd);
        }
    }
    private:
      std::string _path;
      std::string _name;
      std::string _fifoname;  
      int _fd;
};

上面代码主要是对管道文件的文件操作,当拿到文件描述符后如何进行通信

与匿名管道对比:

特性匿名管道命名管道
存在位置内存文件系统
进程关系亲缘任意
生命周期随进程随文件
名称/路径

今天 的更新就到这里,如有错误欢迎评论区指出