通常,共享内存是使用映射到进程地址空间的部分On-Disk文件实现的。每当在共享区域上发生内存访问时,文件系统就会在磁盘上写入更改,这是一个很大的开销。
通常,对fopen()
的调用会返回一个文件描述符,传递给mmap()
以创建文件的内存映射。显然,shm_open
以同样的方式运作。它返回一个文件描述符,甚至可以用于常规文件操作(例如ftruncate
,ftell
,fseek
...等等。我们指定一个字符串作为shm_open
的参数,但与fopen()
不同,它不是可见文件系统上的真实文件的名称(已安装的HDD,闪存驱动器,SSD等)。完全不相关的进程可以使用相同的字符串名称将相同的区域映射到它们的地址空间中。
那么,传递给shm_open
&的字符串参数是什么? shm_open
创建/打开了什么?它是一个临时文件系统(/ tmp)上的文件,最终被许多进程用来创建共享区域(嗯,我认为它必须是某种文件,因为它返回文件描述符)?或者它是由内核支持的某种神秘且隐藏的文件系统?
人们说shm_open
比fopen
快,因为没有涉及磁盘操作,所以我建议的理论是内核使用一个不可见的基于RAM的文件系统来实现与shm_open
的共享内存!
答案 0 :(得分:5)
通常,共享内存是使用映射到进程地址空间的部分On-Disk文件实现的。
这通常是错误的,至少在运行最新Linux发行版的台式机或笔记本电脑上,有一些合理数量的RAM(例如至少8Gbytes)。
因此,磁盘不相关。您可以使用shm_open
而无需任何交换。请参阅shm_overview(7),并注意/dev/shm/
通常是tmpfs已安装的文件系统,因此请勿使用任何磁盘。见tmpfs(5)。并且tmpfs
不使用该磁盘(除非您达到thrashing条件,这是不太可能的),因为它适用于virtual memory。
文件系统涉及在磁盘上写入更改,这是一个很大的开销。
这通常是错误的。在大多数系统上,最近编写的文件位于page cache,但没有快速到达磁盘(BTW,这就是为什么关机程序需要调用sync(2),这很少用,否则......)。
BTW,在大多数台式机和笔记本电脑上,很容易观察到。硬盘有一些LED,使用shm_open
及相关呼叫时,您不会看到它闪烁。顺便说一句,您也可以使用proc(5)(尤其是/proc/diskstats
等....)来查询内核的磁盘活动。
答案 1 :(得分:5)
通常,共享内存是使用映射到进程地址空间的部分On-Disk文件实现的。每当在共享区域上发生内存访问时,文件系统就会在磁盘上写入更改,这是一个很大的开销。
这似乎相当冒昧,并不完全正确。基本上所有实现共享内存区域的机器(在IPC意义上)都具有虚拟内存单元,通过它们支持该功能。可能有也可能没有任何持久存储支持任何特定的共享内存段或其任何部分。只有被分页的部分(如果有的话)才需要由此类存储支持。
显然,
shm_open
以同样的方式运作。它返回一个文件描述符,甚至可以用于常规文件操作(例如ftruncate
,ftell
,fseek
...等等。
shm_open()
具有以open()
为模型的接口,并且它返回一个可以与某些通用I / O函数有意义地使用的文件描述符,并不意味着shm_open()
在更广泛的意义上,“以相同的方式工作”。几乎所有系统资源都表示为进程作为文件。这提供了一个更简单的整体系统接口,但它并不意味着底层资源的任何共性,除了它们可以通过相同的功能进行操作 - 实际上它们可以实现。
那么,传递给
shm_open
&的字符串参数是什么?shm_open
创建/打开了什么?
该参数是标识共享内存段的字符串。你已经知道了,但你似乎认为它还有更多。至少没有指定shm_open
接口的级别(POSIX)。标识符主要对内核有意义。不同的实现以不同的方式处理细节。
它是某个临时文件系统(/ tmp)上的文件,最终被许多进程用来创建共享区域
可能,但可能不是。为其提供的任何文件系统接口很可能(但不确定)是虚拟文件系统,而不是磁盘上的实际可访问文件。持久存储(如果使用)可能是在系统的交换空间之外提供的。
(嗯,我认为它必须是某种文件,因为它返回文件描述符)?
这样的结论是没有根据的。套接字和管道也通过文件描述符表示,但它们没有相应的可访问文件。
或者它是由内核支持的某种神秘且隐藏的文件系统?
这可能是一个更好的概念,但同样,可能根本没有任何持久存储。然而,在某种程度上,它可能是系统交换空间的一部分,这并不是那么神秘。