【发布时间】:2013-01-24 13:51:32
【问题描述】:
我正在尝试通过LD_PRELOAD 替换预先识别的fd 上的原始mmap() 系统调用,以便调用它的进程可以读取另一个进程先前使用boost::interprocess 创建的共享内存对象。一切都很顺利,除非我最终尝试读取 mmap'ed 内存。在这种情况下,第一个进程会因分段错误而中止。可能是什么原因?我不需要共享内存对象的写权限。
这是预加载库中的代码:
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 failed\n";
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());
试图读取上面共享内存的程序(段错误)的代码是:
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替换代码吗?它可能有问题。 -
我会尽快的。
-
您确定要用您自己的实现替换流程中的每一个 mmap() 调用吗?如果您使用的是 LD_PRELOAD 技巧,那正是将会发生的事情......
-
替换实际上只发生在预先确定的 fd 上明确定义的条件下。在所有其他情况下,都会调用原始 mmap。实际上拦截本身很好,我可以获得共享对象,它的大小,我还可以获得区域起始地址并在 mmap() 中返回它。但是一旦我在 mmap() 之后读取内存,就会出现段错误。
-
您的
mmap()替换可重入吗?它可能正在做的一些事情(包括打印调试输出!)本身可能会触发通过匿名mmap()服务的分配。