带有LD_PRELOAD和boost::interprocess的mmap()不起作用

mmap() with LD_PRELOAD and boost::interprocess does not work

本文关键字:mmap 不起作用 interprocess 带有 PRELOAD boost LD      更新时间:2023-10-16

我正试图通过LD_PRELOAD替换预先识别的fd上的原始mmap()系统调用,以便调用它的进程可以读取另一个进程先前使用boost::interprocess创建的共享内存对象。一切都很顺利,只有当我终于试着去读电影的记忆时。在这种情况下,第一个进程因分段故障而中止。原因可能是什么?我不需要对共享内存对象拥有写权限。

这是预加载库中的代码:

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) {
    static void* (*o_mmap) ( void *, size_t, int, int, int, off_t ) =
       o_mmap = (void*(*)( void *, size_t, int, int, int, off_t )) dlsym(RTLD_NEXT, "mmap");
    if (!o_mmap)
        std::cout << "mmap() preload failedn";
    if (fd != my_fd)
        return (*o_mmap)( start, length, prot, flags, fd, offset );
    interprocess::shared_memory_object shm (interprocess::open_only, "obj", interprocess::read_only);
    interprocess::mapped_region region(shm, interprocess::read_only, 0, length, start);
    std::cout << "mmap() overridden. addr =" << region.get_address()  << " length: " << region.get_size() << " start: " << start << "n";
    return region.get_address();
}

创建共享内存对象的程序代码为:

  //Create a shared memory object.
  shared_memory_object shm (create_only, "obj", read_write);
  //Set size
  shm.truncate(1000);
  //Map the whole shared memory in this process
  mapped_region region(shm, read_write);
  //Write all the memory to 1
  std::memset(region.get_address(), 1, region.get_size());

尝试读取上面共享内存的程序(其中segfault)的代码是:

  int fd = open(my_file, O_RDONLY);
  void* addr = mmap(0, 1000, PROT_READ, MAP_SHARED, fd, 0); // Okay
  //Check that memory was initialized to 1
  char *mem = static_cast<char*>(addr); 
  for(std::size_t i = 0; i < 1000; ++i)
     if(*mem++ != 1) // SEGFAULT!
        return 1;   //Error checking memory

您的问题是,您实际上是在以一种稍微模糊的方式返回对本地的引用。mmap()重写在堆栈上有一个interprocess::shared_memory_objectinterprocess::mapped_region,当您返回到客户端时,它们会被销毁。在销毁过程中,boost包装器将取消映射内存区域,因此在客户端代码中访问它不再有效。作为一个简单的解决方案,使这些变量为静态可以防止seg错误,尽管根据应用程序的结构,可能需要更复杂的解决方案。