Linux---命名管道与共享内存(一)

一、命名管道的本质

命名管道必须在磁盘中存在,是一个真实的文件,这是一种特殊的文件,管道文件。

命名管道(FIFO)在文件系统中表现为一个特殊的管道文件(类型为 p) ,它有自己的路径和文件名,看起来像 "存在于磁盘上",但实际并不占用磁盘存储空间 ,数据是存储在内核缓冲区里的,只是通过文件系统的路径来标识和访问。

有了inode那么这个文件一定会具有名字。

如何保证打开的是同一个文件?

  1. 在 Linux/Unix 系统中,每个文件都有一个唯一的 inode 号(索引节点),它是文件在文件系统中的唯一标识。

  2. 只要多个进程访问同一个路径 + 文件名,就会定位到同一个 inode,从而保证打开的是同一个命名管道文件。

    • 这也是命名管道能让无亲缘关系的进程互相通信的关键 ------ 通过共享的路径名找到同一个管道。

创建命名管道mkfifo

在文件系统里创建一个命名管道文件,用于进程间通信。

命名管道的属性:

不在磁盘里所以不占空间所以大小为0.

接下来我们进行编写代码:

代码如下:

cpp 复制代码
//client.cc
#include<iostream>
#include"Pipe.hpp"
//向命名管道写

int main()
{
    Fifo fileclient;
    fileclient.open(ForWrite);

    while(true)
    {
        std::cout<<"Please Enter@ "; 
        std::string msg;
        std::fetline(std::cin,msg);
        fileclient.Send(msg);
    }
    
    
}
cpp 复制代码
//server.cc
//向命名管道读
#include"Pipe.hpp"
int main()
{
    Fifo pipefile;
    pipefile.Build();
    pipeile.Open(ForRead);
    std::string msg;


    while(true)
    {

        pipefile.Recv(&msg);
        if (n>0)
        {
            std::cout<<"Client Say# "<<msg<<std::endl;
        }
        else 
            break;
    }

    pipefile.Delete();
    

    return 0;
    
}
cpp 复制代码
//pipe.hpp
#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

const std::string gcommfile = "./fifo";
#define ForRead 1
#define ForWrite 2
class Fifo
{
public:
    Fifo(const std::string &commfile = gcommfile)
        : _commfile(commfile), _mode(0666), _fd(-1)
    {
    }
    // 1、创建管道
    void Build()

    {
        if (IsExists())
            return;
        umask(0);
        int n = mkfifo(_commfile.c_str(), _mode);
        if (n < 0)
        {
            std::cerr << " mkfifo error:" << strerror(errno) << "errno:" << errno << std::endl;
            exit(1);
        }
        std::cerr << " mkfifo error:" << strerror(errno) << "errno:" << errno << std::endl;
    }
    // 2、打开管道
    void Open(int mode)
    {
        //在通信没有开始之前,如果读端打开,写端没有打开,读端open就会阻塞,直到client(写端)打开
        if (mode == ForRead)

            _fd = open(_commfile.c_str(), O_RDONLY);

        else if(mode == ForWrite)
                _fd = open(_commfile.c_str(), O_WRONLY);
    }


    void Send(const std::string &msgin)
    {
        ssize_t n=write(_fd,msgin.c_str(),msginsize());
        (void)n;

    }
    void Recv(const std::string &msgout)
    {
        char buffer[128];

        ssize_t n=read(_fd,buffer,sizeof(buffer)-1);
        if(n>0)
        {
            buffer[n]=0;
            *msgout=buffer;
            return n;
        }
        else if (n==0)
        {
            return 0;
        }
        else 
        {
            return -1;
        }
    }
    // 3、删除管道
    void Delete()
    {
        if (!IsExists())
            return;
        int n = unlink(_commfile.c_str());
        (void)n;
    }
    ~Fifo()
    {
    }

private:
    bool IsExists()
    {
        struct stat st;
        int n = stat(_commfile.c_str(), &st);
        if (n == 0)
        {
            std::cout << "file exists" << std::cout << endl;
            return true;
        }
        else
        {
            std::cout << "file not exist exists:" << errno << std::endl;
            return false;
        }
    }

private:
    std::string _commfile;
    mode_t _mode;
    int _fd;
};
cpp 复制代码
//Makefile
.PHONY:all
all: Client Server

Client: client.cc
	g++ -o $@ $^ -std=c++11

Server: server.cc
	g++ -o $@ $^ -std=c++11

.PHONY: clean
clean:
	rm -f Server Client

二、system V共享内存

1、原理是什么?

1、映射到进程的虚拟空间地址的共享区。2、共享内存是一个简化版本的动态库映射。

3、共享内存=共享内存管理结构体+共享内存本身

共享内存需要被操作系统管理起来

4、使用共享内存的步骤:1、创建2、关联链接3、使用()4、去关联5、释放共享内

共享内存是什么?

答:采用多个进程,使用虚拟地址空间映射的方式,让不同的进程看到同一个内存块。

接口:

相关推荐
by2099910 分钟前
Linux 基础指令与文件操作
linux·1024程序员节
2401_8685347833 分钟前
软考网络规划设计师SSL协议知识点详解
服务器·网络
Escalating_xu1 小时前
【Linux 网络编程】手写序列化与反序列化:从 x op y 到能校验的文本协议
linux·运维·网络
润滑卫士1 小时前
油液多参数融合故障诊断:数据级融合与决策级融合方法
运维
李纲明2 小时前
WordPress 后台登录马上被踢回登录页:Cookie 域、HTTPS、盐值和页面缓存怎么查
运维·缓存·https·php·wordpress·cookie
todoitbo2 小时前
在 Ubuntu ARM64 上运行 Q1 V3.0 MuJoCo 模型:加载、步进和单执行器响应
linux·运维·ubuntu·ai·机器人·仿真教程·启元
AR-26710-3 小时前
Linux Day26——传输层与三次握手
linux·运维
隔窗听雨眠4 小时前
PostgreSQL单表从Windows迁移到Linux:差异剖析、方案对比与全流程实战
linux·windows·postgresql
xinruoqianqiu4 小时前
记录Linux
linux
额额额对了4 小时前
嵌入式 Linux 实战:i.MX6ULL 上的 CAN 通信与摄像头采集
linux·运维·服务器