温馨提示×

C++ Linux程序如何进行内存映射

小樊
44
2025-12-14 23:44:45
栏目: 编程语言

在Linux环境下,C++程序可以通过多种方式实现内存映射。以下是几种常用的方法:

1. 使用 mmap 系统调用

mmap 是一个系统调用,用于将文件或设备映射到进程的地址空间。它也可以用于匿名映射(不对应任何文件)。

示例代码:

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>

int main() {
    // 打开一个文件
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    // 获取文件大小
    off_t length = lseek(fd, 0, SEEK_END);
    lseek(fd, 0, SEEK_SET);

    // 映射文件到内存
    void* addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        close(fd);
        return 1;
    }

    // 使用映射的内存
    std::cout << static_cast<char*>(addr) << std::endl;

    // 解除映射
    if (munmap(addr, length) == -1) {
        perror("munmap");
    }

    close(fd);
    return 0;
}

2. 使用 mmap 进行匿名映射

匿名映射不对应任何文件,通常用于共享内存。

示例代码:

#include <sys/mman.h>
#include <unistd.h>
#include <iostream>

int main() {
    // 创建匿名映射
    void* addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        return 1;
    }

    // 使用映射的内存
    int* data = static_cast<int*>(addr);
    *data = 42;

    std::cout << "Data: " << *data << std::endl;

    // 解除映射
    if (munmap(addr, 4096) == -1) {
        perror("munmap");
    }

    return 0;
}

3. 使用 POSIX 共享内存

POSIX 共享内存允许进程间共享内存区域。

示例代码(创建共享内存):

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <string.h>

int main() {
    const char* name = "/my_shm";
    int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open");
        return 1;
    }

    // 设置共享内存大小
    if (ftruncate(shm_fd, sizeof(int)) == -1) {
        perror("ftruncate");
        close(shm_fd);
        shm_unlink(name);
        return 1;
    }

    // 映射共享内存
    void* addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        close(shm_fd);
        shm_unlink(name);
        return 1;
    }

    // 使用共享内存
    int* data = static_cast<int*>(addr);
    *data = 42;

    std::cout << "Shared Data: " << *data << std::endl;

    // 解除映射
    if (munmap(addr, sizeof(int)) == -1) {
        perror("munmap");
    }

    close(shm_fd);
    shm_unlink(name);
    return 0;
}

示例代码(访问共享内存):

#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <string.h>

int main() {
    const char* name = "/my_shm";
    int shm_fd = shm_open(name, O_RDONLY, 0666);
    if (shm_fd == -1) {
        perror("shm_open");
        return 1;
    }

    // 映射共享内存
    void* addr = mmap(NULL, sizeof(int), PROT_READ, MAP_SHARED, shm_fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        close(shm_fd);
        shm_unlink(name);
        return 1;
    }

    // 访问共享内存
    int* data = static_cast<int*>(addr);
    std::cout << "Shared Data: " << *data << std::endl;

    // 解除映射
    if (munmap(addr, sizeof(int)) == -1) {
        perror("munmap");
    }

    close(shm_fd);
    shm_unlink(name);
    return 0;
}

4. 使用 boost::interprocess

boost::interprocess 是一个跨平台的库,提供了丰富的内存管理功能,包括共享内存、内存映射文件等。

示例代码:

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <iostream>
#include <cstring>

namespace bip = boost::interprocess;

int main() {
    // 创建或打开共享内存对象
    bip::shared_memory_object shm(bip::open_or_create, "MySharedMemory", bip::read_write);
    shm.truncate(sizeof(int));

    // 映射共享内存
    bip::mapped_region region(shm, bip::read_write);
    void* addr = region.get_address();

    // 使用映射的内存
    int* data = static_cast<int*>(addr);
    *data = 42;

    std::cout << "Shared Data: " << *data << std::endl;

    return 0;
}

总结

以上方法各有优缺点,选择合适的方法取决于具体的应用场景和需求。mmap 系统调用提供了底层的内存映射功能,而 POSIX 共享内存和 boost::interprocess 则提供了更高层次的抽象,简化了共享内存的管理。

0