Linux 如何为 mmap 选择固定地址?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6446101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I choose a fixed address for mmap?
提问by SoapBox
mmap()
can be optionally supplied with a fixed location to place the map. I would like to mmap a file and then have it available to a few different programs at the same virtual address in each program. I don't care what the address is, just as long as they all use the same address. If need be, the address can be chosen by one of them at run time (and communicated with the others via some other means).
mmap()
可以选择提供一个固定位置来放置地图。我想映射一个文件,然后让它可用于每个程序中相同虚拟地址的几个不同程序。我不在乎地址是什么,只要它们都使用相同的地址即可。如果需要,地址可以由其中之一在运行时选择(并通过其他方式与其他人通信)。
Is there an area of memory that Linux guarantees to be unused (by the application and by the kernel) that I can map to? How can I find one address that is available in several running applications?
是否有我可以映射到 Linux 保证未使用的内存区域(由应用程序和内核使用)?如何找到在多个正在运行的应用程序中可用的一个地址?
采纳答案by TomH
Not really, no. With address space randomisation on modern linux systems it is very hard to guarantee anything about what addresses may or may not be used.
不是真的,不是。通过现代 linux 系统上的地址空间随机化,很难保证可以使用或不使用哪些地址。
Also, if you're thinking of using MAP_FIXED
then be aware that you need to be very careful as it will cause mmap to unmap anything that may already be mapped at that address which is generally a very bad thing.
此外,如果您正在考虑使用,MAP_FIXED
那么请注意您需要非常小心,因为它会导致 mmap 取消映射任何可能已经映射到该地址的内容,这通常是一件非常糟糕的事情。
I really think you will need to find another solution to your problem...
我真的认为您需要为您的问题找到另一种解决方案......
回答by Jason
You could look into doing a shared memory object using shmget()
, shmat()
, etc. First have the process that obtains the right to initialize the shared memory object read in your file and copy it into the shared memory object address space. Now any other process that simply gets a return shared memory ID value can access the data in the shared memory space. So for instance, you could employ some type initialization scheme like the following:
您可以考虑使用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 ...
The last process to use the shared memory object, will, just before destroying it, copy the modified contents from shared memory back into the actual file. You may also want to allocate a structure at the beginning of your shared memory object that can be used for synchronization, i.e., there would be some type of "magic number" that the initializing process will set so that your other processes will know that the data has been properly initialized in the shared memory object before accessing it. Alternatively you could use a named semaphore or System V semaphore to make sure that no process tries to access the shared memory object before it's been initialized.
使用共享内存对象的最后一个进程将在销毁它之前,将修改后的内容从共享内存复制回实际文件。您可能还想在共享内存对象的开头分配一个可用于同步的结构,即,初始化过程将设置某种类型的“幻数”,以便您的其他进程知道数据在访问之前已在共享内存对象中正确初始化。或者,您可以使用命名信号量或 System V 信号量来确保在初始化之前没有进程尝试访问共享内存对象。
回答by bobwirka
Two processes can map a shared memory block to the same virtual address using shm_open() and mmap(); that is, the virtual address returned from mmap() can be the same for both processes. I found that Linux will by default give different virtual addresses to different processes for the same piece of shared memory, but that using mmap() with MAP_FIXED will force Linux to supply the same virtual address to multiple processes.
两个进程可以使用 shm_open() 和 mmap() 将共享内存块映射到同一个虚拟地址;也就是说,从 mmap() 返回的虚拟地址对于两个进程可以是相同的。我发现 Linux 会默认为同一块共享内存的不同进程提供不同的虚拟地址,但是使用 mmap() 和 MAP_FIXED 将强制 Linux 为多个进程提供相同的虚拟地址。
The process that creates the shared memory block must store the virtual address somewhere, either within the shared memory, in a file, or with some other method so that another process can determine the original virtual address. The known virtual address is then used in the mmap() call, along with the MAP_FIXED flag.
创建共享内存块的进程必须将虚拟地址存储在某个地方,或者在共享内存中,在文件中,或者使用某种其他方法,以便另一个进程可以确定原始虚拟地址。然后在 mmap() 调用中使用已知的虚拟地址以及 MAP_FIXED 标志。
I was able to use the shared memory to do this. When doing so, the "golden" virtual address is stored within the shared memory block; I made a structure that contains a number of items, the address being one of them, and initialized it at the beginning of the block.
我能够使用共享内存来做到这一点。这样做时,“黄金”虚拟地址存储在共享内存块中;我创建了一个包含多个项目的结构,地址是其中之一,并在块的开头对其进行了初始化。
A process that wants to map that shared memory must execute the mmap() function twice; once to get the "golden" virtual address, then to map the block to that address using the MAP_FIXED flag.
想要映射共享内存的进程必须执行 mmap() 函数两次;一次获得“黄金”虚拟地址,然后使用 MAP_FIXED 标志将该块映射到该地址。
Interestingly, I'm working with an embedded system running a 2.6 kernel. It will, by default, supply the same virtual address to all mmap() calls to a given file descriptor. Go figure.
有趣的是,我正在使用运行 2.6 内核的嵌入式系统。默认情况下,它将为给定文件描述符的所有 mmap() 调用提供相同的虚拟地址。去搞清楚。
Bob Wirka
鲍勃·维尔卡