如何为mmap选择固定地址?

时间:2011-06-22 20:23:34

标签: c linux mmap

可以选择为

mmap()提供固定位置以放置地图。我想mmap一个文件,然后让它可用于每个程序中相同虚拟地址的几个不同的程序。我不在乎地址是什么,只要他们都使用相同的地址。如果需要,可以在运行时由其中一个人选择地址(并通过其他方式与其他人通信)。

是否存在Linux保证未使用的内存区域(由应用程序和内核),我可以映射到哪个区域?如何在多个正在运行的应用程序中找到一个可用的地址?

3 个答案:

答案 0 :(得分:7)

不是,不。随着现代Linux系统上的地址空间随机化,很难保证可以使用或不使用哪些地址。

另外,如果您正在考虑使用MAP_FIXED,那么请注意您需要非常小心,因为它会导致mmap取消映射可能已经映射到该地址的任何内容,这通常是一件非常糟糕的事情

我真的认为你需要为你的问题找到另一种解决方案......

答案 1 :(得分:3)

两个进程可以使用shm_open()和mmap()将共享内存块映射到同一个虚拟地址;也就是说,从mmap()返回的虚拟地址对于两个进程都可以是相同的。我发现默认情况下Linux会为同一块共享内存的不同进程提供不同的虚拟地址,但是使用带有MAP_FIXED的mmap()会强制Linux为多个进程提供相同的虚拟地址。

创建共享内存块的过程必须将虚拟地址存储在共享内存中,文件中或其他方法中,以便其他进程可以确定原始虚拟地址。然后,在mmap()调用中使用已知的虚拟地址以及MAP_FIXED标志。

我能够使用共享内存来执行此操作。这样做时,“黄金”虚拟地址存储在共享内存块中;我创建了一个包含许多项的结构,地址就是其中之一,并在块的开头初始化它。

要映射共享内存的进程必须执行两次mmap()函数;一次获取“黄金”虚拟地址,然后使用MAP_FIXED标志将块映射到该地址。

有趣的是,我正在使用运行2.6内核的嵌入式系统。默认情况下,它将为给定文件描述符的所有mmap()调用提供相同的虚拟地址。去图。

Bob Wirka

答案 2 :(得分:2)

您可以使用shmget()shmat()等来查看共享内存对象。首先要获得初始化文件中读取的共享内存对象并将其复制到文件中的权限的过程。共享内存对象地址空间。现在,任何其他只获取返回共享内存ID值的进程都可以访问共享内存空间中的数据。因此,例如,您可以采用以下类型的初始化方案:

#include <sys/shm.h>

#define KEYVALUE 1000 //arbitrary value ... just needs to be shared between your processes

int file_size
//read your file and obtain its size in bytes;

//try to create the shared memory object
int shared_mem_id;
void* shared_mem_ptr = NULL;

if ((shared_mem_id = shmget(KEYVALUE, file_size, S_IRUSR | S_IWUSR IPC_CREAT | IPC_EXCL)) == -1)
{
    if (errno == EEXIST)
    {
        //shared memory segment was already created, so just get its ID value
        shared_mem_id = shmget(KEYVALUE, file_size, S_IRUSR | S_IWUSR);
        shared_mem_ptr = shmat(shared_mem_id, NULL, 0)
    }
    else
    {
        perror("Unable to create shared memory object");
        exit(1);
    }
}
else
{
    shared_mem_ptr = shmat(shared_mem_id, NULL, 0);

    //copy your file into shared memory via the shared_mem_ptr

}

//work with the shared data ...

使用共享内存对象的最后一个进程,在销毁之前,将修改后的内容从共享内存复制回实际文件中。您可能还希望在共享内存对象的开头分配一个可用于同步的结构,即初始化过程将设置某种类型的“幻数”,以便您的其他进程知道数据在访问之前已在共享内存对象中正确初始化。或者,您可以使用命名信号量或System V信号量来确保在初始化之前没有进程尝试访问共享内存对象。