【Linux进阶】mmap实战:文件映射、进程通信与LRU缓存

【Linux进阶】mmap实战:文件映射、进程通信与LRU缓存

mmap(内存映射)是Linux系统中高效的I/O技术,它将文件或设备直接映射到进程虚拟地址空间,无需通过read/write系统调用拷贝数据,大幅提升读写性能。除了基础文件操作,mmap还广泛应用于进程间通信、内存分配、缓存设计等场景。

一、mmap基础:原理与核心用法

1.1 什么是mmap?

mmap通过内核将文件/设备的部分或全部内容映射到进程虚拟地址空间,进程直接操作这段内存即可完成对文件的读写。其核心优势在于:

  • 减少数据拷贝:跳过内核缓冲区与用户缓冲区的拷贝过程。
  • 统一接口:用内存操作(指针读写)替代文件I/O调用。
  • 支持共享:可通过共享映射实现进程间数据共享。

1.2 核心接口与参数解析

cpp 复制代码
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
关键参数说明
参数 作用
addr 期望的映射起始地址,传NULL让内核自动分配
length 映射长度(必须是系统页大小的整数倍,默认4KB)
prot 内存保护属性:PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)
flags 映射类型:MAP_SHARED(共享映射,修改同步到文件)、MAP_PRIVATE(私有映射,写时拷贝)
fd 待映射文件的文件描述符(匿名映射传-1)
offset 文件起始偏移量(必须是页大小整数倍)
返回值
  • 成功:返回映射区域的虚拟地址指针。
  • 失败:返回MAP_FAILED(即(void*)-1),并设置errno

1.3 基础实战:文件映射读写

1.3.1 写入映射(修改文件内容)
cpp 复制代码
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <cstring>

#define SIZE 4096 // 4KB,页大小整数倍

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " filename" << std::endl;
        return 1;
    }

    std::string filename = argv[1];
    // 以读写模式打开文件(必须支持写才能同步修改)
    int fd = ::open(filename.c_str(), O_CREAT | O_RDWR, 0666);
    if (fd < 0) {
        perror("open");
        return 2;
    }

    // 调整文件大小(默认文件大小为0,无法映射)
    ::ftruncate(fd, SIZE);

    // 创建共享映射
    char *mmap_addr = (char*)::mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, 
                                     MAP_SHARED, fd, 0);
    if (mmap_addr == MAP_FAILED) {
        perror("mmap");
        return 3;
    }

    // 直接操作内存,同步修改文件
    for (int i = 0; i < SIZE; i++) {
        mmap_addr[i] = 'a' + i % 26; // 填充a-z循环
    }

    // 取消映射(修改已同步到文件,无需显式write)
    ::munmap(mmap_addr, SIZE);
    ::close(fd);

    std::cout << "文件映射写入完成" << std::endl;
    return 0;
}
1.3.2 读取映射(高效读取文件)
cpp 复制代码
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " filename" << std::endl;
        return 1;
    }

    std::string filename = argv[1];
    int fd = ::open(filename.c_str(), O_RDONLY);
    if (fd < 0) {
        perror("open");
        return 2;
    }

    // 获取文件实际大小
    struct stat st;
    ::fstat(fd, &st);

    // 创建只读映射
    char *mmap_addr = (char*)::mmap(nullptr, st.st_size, PROT_READ, 
                                     MAP_SHARED, fd, 0);
    if (mmap_addr == MAP_FAILED) {
        perror("mmap");
        return 3;
    }

    // 直接读取内存(无需read调用)
    std::cout << "文件内容:" << std::endl;
    std::cout << mmap_addr << std::endl;

    ::munmap(mmap_addr, st.st_size);
    ::close(fd);
    return 0;
}

1.4 进阶:用mmap模拟malloc内存分配

mmap支持匿名映射(MAP_ANONYMOUS),无需关联文件,可直接分配内存,实现简易版malloc

cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

// 自定义malloc:基于匿名映射
void* my_malloc(size_t size) {
    // MAP_PRIVATE:私有映射,进程间不可见
    // MAP_ANONYMOUS:匿名映射,无关联文件
    void* ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (ptr == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }
    return ptr;
}

// 自定义free:取消映射
void my_free(void* ptr, size_t size) {
    if (munmap(ptr, size) == -1) {
        perror("munmap");
        exit(EXIT_FAILURE);
    }
}

int main() {
    size_t size = 1024; // 分配1KB内存
    char* ptr = (char*)my_malloc(size);

    printf("分配内存地址:%p\n", ptr);
    memset(ptr, 'A', size); // 填充内存

    // 打印内存内容(每1秒输出一个字符)
    for (int i = 0; i < size; i++) {
        printf("%c ", ptr[i]);
        fflush(stdout);
        sleep(1);
    }

    my_free(ptr, size);
    printf("\n内存释放完成\n");
    return 0;
}

编译运行

bash 复制代码
g++ -o mymalloc mymalloc.cpp -std=c++11
./mymalloc

调试验证 :用gdb查看内存映射:

gdb 复制代码
(gdb) info proc mapping
# 可看到匿名映射的内存区域(无关联objfile)

二、mmap进程间通信:共享内存+同步机制

mmap的共享映射(MAP_SHARED)可实现进程间数据共享,结合互斥锁和条件变量,能实现安全的进程间通信(IPC)。

2.1 设计思路

  • 共享内存载体 :用shm_open创建POSIX共享内存对象,作为mmap的映射源。
  • 同步机制 :在共享内存中嵌入互斥锁(pthread_mutex_t)和条件变量(pthread_cond_t),保证进程间互斥访问。
  • 数据传输:共享内存中预留缓冲区,用于存储进程间通信的数据。

2.2 核心封装:共享内存对象

cpp 复制代码
// SharedMem.hpp
#pragma once
#include <iostream>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

#define SIZE 4096 // 缓冲区大小
#define SHARED_MEMORY_FILE "/shm" // 共享内存对象名称(必须以/开头)
#define SHARED_MEMORY_SIZE sizeof(SafeObj)

// 带同步机制的共享对象
class SafeObj {
public:
    void InitObj() {
        // 初始化进程间共享的互斥锁
        pthread_mutexattr_t mattr;
        pthread_mutexattr_init(&mattr);
        // 设置锁为进程间共享(默认仅线程间共享)
        pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
        pthread_mutex_init(&lock, &mattr);

        // 初始化进程间共享的条件变量
        pthread_condattr_t cattr;
        pthread_condattr_init(&cattr);
        pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
        pthread_cond_init(&cond, &cattr);

        // 清空缓冲区
        memset(buffer, 0, sizeof(buffer));
    }

    void CleanupObj() {
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }

    // 加锁/解锁/等待/通知接口
    void LockObj() { pthread_mutex_lock(&lock); }
    void UnlockObj() { pthread_mutex_unlock(&lock); }
    void Wait() { pthread_cond_wait(&cond, &lock); }
    void Signal() { pthread_cond_signal(&cond); }
    void BroadCast() { 
        int n = pthread_cond_broadcast(&cond);
        std::cout << (n == 0 ? "广播成功" : "广播失败") << std::endl;
    }

    // 数据读写接口
    void GetContent(std::string *out) { *out = buffer; }
    void SetContent(const std::string &in) {
        memset(buffer, 0, sizeof(buffer));
        strncpy(buffer, in.c_str(), in.size());
    }

private:
    pthread_mutex_t lock;       // 进程间互斥锁
    pthread_cond_t cond;        // 进程间条件变量
    char buffer[SIZE];          // 共享缓冲区
};

// 共享内存管理基类
class MmapMemory {
public:
    MmapMemory(const std::string &file, int size) 
        : _file(file), _size(size), _fd(-1), _mmap_addr(nullptr) {}

    ~MmapMemory() {
        if (_fd > 0) close(_fd);
        if (_mmap_addr != MAP_FAILED) {
            munmap(_mmap_addr, _size);
            std::cout << "munmap完成" << std::endl;
        }
    }

    // 打开共享内存对象
    void OpenFile() {
        _fd = shm_open(_file.c_str(), O_CREAT | O_RDWR, 0666);
        if (_fd < 0) {
            perror("shm_open");
            exit(1);
        }
    }

    // 调整共享内存大小
    void TruncSharedMemory() {
        if (ftruncate(_fd, _size) < 0) {
            perror("ftruncate");
            exit(2);
        }
    }

    // 执行mmap映射
    void *Mmap() {
        _mmap_addr = mmap(nullptr, _size, PROT_READ | PROT_WRITE, 
                          MAP_SHARED, _fd, 0);
        if (_mmap_addr == MAP_FAILED) {
            perror("mmap");
            exit(3);
        }
        return _mmap_addr;
    }

    // 删除共享内存对象(仅服务端调用)
    void RemoveFile() {
        if (shm_unlink(_file.c_str()) < 0) {
            perror("shm_unlink");
            exit(4);
        }
    }

    void *MmapAddr() { return _mmap_addr; }

private:
    int _fd;
    int _size;
    std::string _file;
    void *_mmap_addr;
};

// 服务端:创建共享内存,等待客户端消息
class MmapMemoryServer : public MmapMemory {
public:
    MmapMemoryServer() : MmapMemory(SHARED_MEMORY_FILE, SHARED_MEMORY_SIZE) {
        OpenFile();
        TruncSharedMemory();
        Mmap();
        obj = static_cast<SafeObj *>(MmapAddr());
        obj->InitObj();
    }

    ~MmapMemoryServer() {
        obj->CleanupObj();
        RemoveFile();
    }

    // 接收客户端消息
    void RecvMessage(std::string *out) {
        obj->LockObj();
        obj->Wait(); // 等待客户端通知
        obj->GetContent(out);
        obj->UnlockObj();
    }

private:
    SafeObj *obj;
};

// 客户端:连接共享内存,发送消息
class MmapMemoryClient : public MmapMemory {
public:
    MmapMemoryClient() : MmapMemory(SHARED_MEMORY_FILE, SHARED_MEMORY_SIZE) {
        OpenFile();
        Mmap();
        obj = static_cast<SafeObj *>(MmapAddr());
    }

    // 发送消息给服务端
    void SendMessage(const std::string &in) {
        obj->LockObj();
        obj->SetContent(in);
        obj->BroadCast(); // 通知所有等待的服务端进程
        obj->UnlockObj();
    }

private:
    SafeObj *obj;
};

2.3 服务端实现(多进程等待)

cpp 复制代码
// Server.cc
#include "SharedMem.hpp"
#include <sys/wait.h>

// 子进程逻辑:等待并处理消息
void Active(MmapMemoryServer &svr, std::string processname) {
    std::cout << "进程启动:" << processname << std::endl;
    std::string who;
    while (true) {
        svr.RecvMessage(&who);
        // 处理目标进程消息或广播消息
        if (who == processname || who == "all") {
            std::cout << processname << " 被激活!" << std::endl;
        }
        // 退出指令
        if (who == "end") {
            std::cout << processname << " 退出!" << std::endl;
            break;
        }
    }
}

int main() {
    MmapMemoryServer svr;

    // 创建10个子进程
    for (int i = 0; i < 10; i++) {
        pid_t id = fork();
        if (id == 0) {
            std::string name = "process-" + std::to_string(i);
            Active(svr, name);
            exit(0);
        }
    }

    // 主进程也参与等待
    Active(svr, "process-main");

    // 等待所有子进程退出
    for (int i = 0; i < 10; i++) {
        wait(nullptr);
    }

    return 0;
}

2.4 客户端实现(发送控制消息)

cpp 复制代码
// Client.cc
#include "SharedMem.hpp"
#include <string>
#include <iostream>

int main() {
    MmapMemoryClient cli;
    std::string who;

    while (true) {
        std::cout << "请输入目标进程(process-0~9/all/end):";
        std::getline(std::cin, who);
        cli.SendMessage(who);
        if (who == "end") {
            break;
        }
    }

    return 0;
}

2.5 编译运行与效果

编译脚本(Makefile)
makefile 复制代码
.PHONY: all clean
all: server client
server: Server.cc
	g++ -o $@ $^ -lpthread -lrt -std=c++11 -g
client: Client.cc
	g++ -o $@ $^ -lpthread -lrt -std=c++11 -g
clean:
	rm -f server client
运行步骤
  1. 启动服务端:./server
  2. 启动客户端(新终端):./client
  3. 客户端输入指令:
    • 输入process-3:仅process-3被激活
    • 输入all:所有进程被激活
    • 输入end:所有进程退出

运行效果

复制代码
# 服务端输出
进程启动:process-0
进程启动:process-1
...
process-3 被激活!
所有进程 被激活!
process-0 退出!
process-1 退出!
...

三、mmap高级应用:实现大文件LRU缓存

对于GB级大文件,直接加载到内存不现实。利用mmap映射文件块,结合LRU(最近最少使用)算法,可实现高效的文件缓存,提升随机访问性能。

3.1 设计思路

  • 数据结构
    • 双向链表(std::list):存储缓存的文件块,按访问顺序排序(最近访问的在头部)。
    • 哈希表(std::unordered_map):快速查找文件块是否在缓存中,映射偏移量到链表节点。
  • 缓存单元:每个缓存单元对应一个4KB的文件块,包含偏移量、映射地址、状态等信息。
  • LRU策略:缓存满时,淘汰链表尾部(最久未使用)的文件块,取消其mmap映射。

3.2 核心封装:LRU缓存实现

cpp 复制代码
// LRUCache.hpp
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <list>
#include <memory>
#include <unordered_map>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

namespace LRUCache {
// 4KB地址对齐(清除低12位)
#define BLOCK_ADDR_ALIGN(off) (off & ~(0xFFF))
// 块状态标志
#define NORMAL (1 << 0)  // 普通状态
#define NEW (1 << 1)     // 新加入缓存
#define VISIT (1 << 2)   // 被访问
#define DELETE (1 << 3)  // 待删除

const int gblocksize = 4096;    // 缓存块大小(4KB)
const int gcapacity = 3;        // 最大缓存块数量(可调整)
const int gdefaultfd = -1;

// 文件块缓存单元
class DataBlock {
public:
    DataBlock(off_t off, off_t size) 
        : _off(off), _size(size), _addr(nullptr), _status(NEW) {}

    // 映射文件块到内存
    bool DoMap(int fd) {
        _addr = mmap(nullptr, _size, PROT_READ | PROT_WRITE, 
                     MAP_SHARED, fd, _off);
        if (_addr == MAP_FAILED) {
            perror("mmap");
            return false;
        }
        std::cout << "mmap成功:偏移量" << _off << ",地址" << _addr << std::endl;
        return true;
    }

    // 取消映射
    bool DoUnmap() {
        if (munmap(_addr, _size) < 0) {
            perror("munmap");
            return false;
        }
        std::cout << "munmap成功:偏移量" << _off << std::endl;
        return true;
    }

    // 状态操作
    void Status2Normal() { _status = NORMAL; }
    void Status2Visit() { _status = VISIT; }
    bool IsNew() { return _status & NEW; }
    bool IsVisit() { return _status & VISIT; }

    // 获取属性
    off_t Off() { return _off; }
    void *Addr() { return _addr; }
    off_t Size() { return _size; }

    // 调试打印
    void DebugPrint() {
        std::cout << "偏移量:" << _off 
                  << ",大小:" << _size 
                  << ",地址:" << _addr 
                  << ",状态:" << (_status & NEW ? "NEW " : "")
                  << (_status & VISIT ? "VISIT " : "")
                  << (_status & NORMAL ? "NORMAL" : "") << std::endl;
    }

private:
    off_t _off;     // 文件块起始偏移量(4KB对齐)
    off_t _size;    // 文件块大小
    void *_addr;    // 映射后的虚拟地址
    unsigned _status;// 块状态
};

// LRU文件缓存主类
class FileCache {
public:
    FileCache(const std::string &file) 
        : _file(file), _fd(gdefaultfd), _total(0), _cachemaxnum(gcapacity) {
        // 打开文件(必须存在)
        _fd = open(_file.c_str(), O_RDWR);
        if (_fd < 0) {
            perror("open");
            return;
        }
        // 获取文件总大小
        struct stat st;
        if (fstat(_fd, &st) < 0) {
            perror("fstat");
            return;
        }
        _total = st.st_size;
        std::cout << "文件大小:" << _total << "字节" << std::endl;
    }

    ~FileCache() {
        if (_fd != gdefaultfd) {
            close(_fd);
        }
        // 释放所有缓存块的映射
        for (auto &block : _cache) {
            block->DoUnmap();
        }
    }

    // 获取指定偏移量的文件块(核心接口)
    std::shared_ptr<DataBlock> GetBlock(off_t off) {
        // 1. 检查偏移量合法性
        if (!IsOffLegal(off)) {
            std::cerr << "偏移量非法:" << off << std::endl;
            return nullptr;
        }
        // 2. 4KB对齐偏移量(确保块起始地址正确)
        off = BLOCK_ADDR_ALIGN(off);
        // 3. 检查缓存是否命中
        if (IsCached(off)) {
            // 命中:标记为已访问,触发LRU调整
            _hash[off]->Status2Visit();
        } else {
            // 未命中:加载文件块到缓存
            DoCache(off);
        }
        // 4. 执行LRU策略(调整顺序或淘汰)
        DoLRU(off);
        return _hash[off];
    }

    // 打印缓存内容
    void PrintCache() {
        std::cout << "\n---------缓存内容---------" << std::endl;
        for (auto &block : _cache) {
            block->DebugPrint();
        }
        std::cout << "--------------------------\n" << std::endl;
    }

private:
    // 检查偏移量是否在文件范围内
    bool IsOffLegal(off_t off) { return off < _total; }
    // 检查块是否已缓存
    bool IsCached(off_t off) { return _hash.find(off) != _hash.end(); }
    // 检查缓存是否已满
    bool IsCacheFull() { return _cache.size() > _cachemaxnum; }

    // 根据偏移量计算块大小(最后一块可能不足4KB)
    off_t GetSizeFromOff(off_t off) {
        if (off + gblocksize > _total) {
            return _total - off; // 剩余字节数
        }
        return gblocksize;
    }

    // 加载文件块到缓存
    void DoCache(off_t off) {
        off_t blocksize = GetSizeFromOff(off);
        // 创建文件块并映射到内存
        auto block = std::make_shared<DataBlock>(off, blocksize);
        if (!block->DoMap(_fd)) {
            return;
        }
        // 添加到哈希表和链表头部(新块优先级最高)
        _hash[off] = block;
        _cache.push_front(block);
    }

    // 执行LRU策略
    void DoLRU(off_t off) {
        auto block = _hash[off];
        if (!block) return;

        if (block->IsNew()) {
            // 新块:标记为普通状态,缓存满则淘汰尾部
            block->Status2Normal();
            if (IsCacheFull()) {
                // 淘汰最久未使用的块(链表尾部)
                auto &last = _cache.back();
                std::cout << "缓存满,淘汰块:" << last->Off() << std::endl;
                last->DoUnmap();
                _hash.erase(last->Off());
                _cache.pop_back();
            }
        } else if (block->IsVisit()) {
            // 已访问块:移动到链表头部(更新访问顺序)
            block->Status2Normal();
            _cache.remove(block);
            _cache.push_front(block);
            std::cout << "块" << off << "移动到缓存头部" << std::endl;
        }
    }

private:
    std::string _file;                                  // 文件名
    int _fd;                                            // 文件描述符
    off_t _total;                                       // 文件总大小
    std::list<std::shared_ptr<DataBlock>> _cache;       // 缓存链表(LRU顺序)
    std::unordered_map<off_t, std::shared_ptr<DataBlock>> _hash; // 哈希表(快速查找)
    int _cachemaxnum;                                   // 最大缓存块数
};
}

3.3 测试代码

cpp 复制代码
// Main.cc
#include "LRUCache.hpp"
#include <iostream>

using namespace LRUCache;

int main(int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " filename" << std::endl;
        return 1;
    }

    // 1. 创建测试大文件(可选:dd if=/dev/zero of=log.txt bs=4096 count=10)
    std::string filename = argv[1];
    FileCache fc(filename);

    // 2. 测试加载10个不同的块(缓存最大3个,触发淘汰)
    int count = 0;
    while (count < 10) {
        off_t off = count * gblocksize;
        std::cout << "\n加载块:" << off << std::endl;
        fc.GetBlock(off);
        fc.PrintCache();
        count++;
        sleep(1);
    }

    // 3. 测试访问已缓存的块(触发LRU调整)
    while (true) {
        off_t off;
        std::cout << "请输入要访问的偏移量(4KB倍数):";
        std::cin >> off;
        auto block = fc.GetBlock(off);
        if (block) {
            std::cout << "访问成功,块地址:" << block->Addr() << std::endl;
        }
        fc.PrintCache();
    }

    return 0;
}

3.4 编译运行与效果

编译脚本(Makefile)
makefile 复制代码
lrucache: Main.cc
	g++ -o $@ $^ -std=c++17 -g
.PHONY: clean
clean:
	rm -f lrucache
运行步骤
  1. 创建测试大文件(10个4KB块,共40KB):

    bash 复制代码
    dd if=/dev/zero of=log.txt bs=4096 count=10
  2. 运行缓存程序:

    bash 复制代码
    ./lrucache log.txt

模拟运行效果

复制代码
文件大小:40960字节
加载块:0
mmap成功:偏移量0,地址0x7ffff7ffb000
---------缓存内容---------
偏移量:0,大小:4096,地址:0x7ffff7ffb000,状态:NORMAL
--------------------------

加载块:4096
mmap成功:偏移量4096,地址0x7ffff7fca000
---------缓存内容---------
偏移量:4096,大小:4096,地址:0x7ffff7fca000,状态:NORMAL
偏移量:0,大小:4096,地址:0x7ffff7ffb000,状态:NORMAL
--------------------------

# 缓存满(3个块),加载第4个块时淘汰最久未使用的块0
加载块:12288
mmap成功:偏移量12288,地址0x7ffff7fc9000
缓存满,淘汰块:0
munmap成功:偏移量0
---------缓存内容---------
偏移量:12288,大小:4096,地址:0x7ffff7fc9000,状态:NORMAL
偏移量:8192,大小:4096,地址:0x7ffff7fcb000,状态:NORMAL
偏移量:4096,大小:4096,地址:0x7ffff7fca000,状态:NORMAL
--------------------------

四、总结与进阶方向

mmap作为Linux系统的核心技术,其应用场景覆盖文件I/O、进程通信、内存管理、缓存设计等多个领域。本文通过三个实战案例,从基础到高级,完整展现了mmap的核心用法:

  1. 基础用法 :文件映射读写,替代传统read/write,提升I/O效率。
  2. 进程通信:结合共享内存和同步机制,实现高效的IPC通信。
  3. 高级应用:大文件LRU缓存,解决大文件随机访问性能问题。

关键注意事项

  1. 映射长度和偏移量必须是系统页大小(默认4KB)的整数倍。
  2. 共享映射(MAP_SHARED)需确保文件以可写模式打开,否则修改无法同步。
  3. 进程间共享锁/条件变量时,必须设置PTHREAD_PROCESS_SHARED属性。
  4. 用完映射后需调用munmap释放,否则会造成内存泄漏。

进阶学习方向

  1. 性能优化 :结合msync控制共享映射的同步时机,平衡性能与数据一致性。
  2. 异常处理:处理信号中断、文件截断、映射区域越界等异常场景。
  3. 扩展应用:实现共享内存池、零拷贝网络传输、内存映射数据库等高级场景。
  4. 跨平台兼容 :研究Windows系统的CreateFileMapping,实现跨平台的内存映射方案。
相关推荐
liuyao_xianhui13 分钟前
版本控制器git--gdb/cgdb
linux·运维·服务器·git
chuxinweihui32 分钟前
应用层协议 HTTP
linux·服务器·网络·网络协议·http
YJlio33 分钟前
「C++ 40 周年」:从“野蛮生长的指针地狱”到 AI 时代的系统底座
c++·人工智能·oracle
xu_yule39 分钟前
Linux_16(多线程)信号量+基于环形队列的生成消费模型+自选锁+读写锁
linux·运维·服务器
行初心1 小时前
uos基础 systemctl 查看unit的详细配置
运维
eyuiomvtywn1 小时前
阿里云DNS解析Vercel部署项目的域名
运维·服务器·阿里云
纵有疾風起1 小时前
C++——多态
开发语言·c++·经验分享·面试·开源
4t4run1 小时前
25、Linux 特殊权限
linux·运维
S***y3962 小时前
DevOps监控告警体系
运维·devops