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

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

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

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

1.1 什么是mmap?

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

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

1.2 核心接口与参数解析

#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 写入映射(修改文件内容)
#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 读取映射(高效读取文件)
#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

#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;
          }

编译运行

g++ -o mymalloc mymalloc.cpp -std=c++11
./mymalloc

调试验证:用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 核心封装:共享内存对象

// 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 服务端实现(多进程等待)

// 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 客户端实现(发送控制消息)

// 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)
.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缓存实现

// 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 测试代码

// 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)
lrucache: Main.cc
	g++ -o $@ $^ -std=c++17 -g
.PHONY: clean
clean:
	rm -f lrucache
运行步骤
  1. 创建测试大文件(10个4KB块,共40KB):
    dd if=/dev/zero of=log.txt bs=4096 count=10
  2. 运行缓存程序:
    ./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,实现跨平台的内存映射方案。
posted @ 2025-12-18 12:52  yangykaifa  阅读(5)  评论(0)    收藏  举报