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、释放共享内

共享内存是什么?

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

接口:

相关推荐
小鸡食米2 小时前
Linux 防火墙
linux·运维·服务器
bingHHB2 小时前
聚水潭 × 金蝶云星空:日均万单电商如何实现销售出库自动记账
运维·自动化·集成学习
ICT系统集成阿祥2 小时前
BGP邻居状态机详解
运维·服务器
海盗猫鸥2 小时前
「Linux工具」自动化构建make/Makfile
linux
NineData2 小时前
MySQL到StarRocks 同步链路中的建表、DDL 跟随与数据校验
运维·数据库·starrocks·mysql·数据迁移·数据库管理工具·ninedata
星晨雪海2 小时前
MyBatis-Plus 常用 CRUD 方法大全
linux·tomcat·mybatis
2739920292 小时前
Ubuntu 文件系统修复指南
linux·ubuntu·fsck
a8a3022 小时前
IPV6公网暴露下的OPENWRT防火墙安全设置(只允许访问局域网中指定服务器指定端口其余拒绝)
服务器·安全·php
云栖梦泽2 小时前
Linux内核与驱动:2.驱动基础(编译驱动)
linux·服务器·c++