关闭和取消映射 POSIX 共享内存对象
Closing and Unmapping POSIX shared memory object
我目前正在使用 POSIX 命名信号量和共享内存进行一些工作,并且我从手册页中了解到所有打开的命名信号量都会在进程终止时自动关闭。共享内存对象也是这种情况吗,它们是否也已关闭且未映射或只是关闭?我在手册页上找不到关于此的任何信息。
Is this also the case for shared memory objects, are they also closed
and unmapped or simply just closed?
它们未映射,但如果未明确取消链接,它们可能会继续占用 space 后备文件系统(通常 tmpfs/shmfs 用于 /dev/shm 在内存中)。
在 FreeBSD 上,可以使用不可移植的 SHM_ANON 标志来自动取消链接。如果您想要这种行为,您可以:
- 使用带有 MAP_ANONYMOUS 标志的 mmap(2) 并通过 fork(2) 共享文件描述符或使用 Unix 域套接字通过 sendmsg(2) 将它们发送到其他进程。
- 使用带有 IPC_RMID 标志的 System V 共享内存,它会在最后一个进程分离内存段后自动销毁它。分离发生在进程终止或调用 shmdt(2) 时。
- 仅使用较新的 Linux memfd_create(2) 系统调用。
问题似乎是关于如何以及何时清理一个或多个进程使用的 POSIX 共享内存,或者可能是关于如何避免共享内存被过早清理。
POSIX 共享内存是在有意类似于常规文件访问的模型上设计的。特别是,
shm_open()
将创建并打开一个新的、持久的 shared-memory object 或简单地打开一个现有的,具体取决于是否已经存在具有指定名称的。
- 该区域可以由其他进程打开(因此必须持续存在)直到通过
shm_unlink()
. 取消链接
- 只要任何进程打开共享内存区域,它在取消链接后就会存在,但无法再通过
shm_open()
. 打开
- 通过
mmap()
映射共享内存区域具有在映射就位时保持打开状态的效果,与用于映射它的文件描述符无关
此外,shared-memory 区域的内存映射在大多数方面与常规文件的映射相同。映射是 per-process 属性;它们不会在它们所属的进程终止后继续存在。映射在 fork()
秒内保留(复制)。
在某些系统上,甚至可以通过文件系统访问共享内存区域。除了管理它们的不同功能外,它们与常规文件的最大区别可能是它们不会在重新启动后保留。
因此,您不必担心进程的终止会意外地破坏其他进程正在使用的共享内存区域。另一方面,您可以安排 shared-memory 区域自动清理,方法是在每个需要按名称获取访问权限的进程完成后取消链接。如果您打算仅授予 child 进程(以及他们的 children 等)的访问权限,那么您可以在创建后立即取消链接。 Children 将在您分叉它们时继承映射。
因此,针对实际问题:
Is this also the case for shared memory objects, are they also closed and unmapped or simply just closed?
进程终止时,进程打开和/或映射的共享内存 object 将同时关闭和取消映射,但它们不会自动取消链接。它们至少会持续存在,直到手动取消链接或系统重新启动。
我目前正在使用 POSIX 命名信号量和共享内存进行一些工作,并且我从手册页中了解到所有打开的命名信号量都会在进程终止时自动关闭。共享内存对象也是这种情况吗,它们是否也已关闭且未映射或只是关闭?我在手册页上找不到关于此的任何信息。
Is this also the case for shared memory objects, are they also closed and unmapped or simply just closed?
它们未映射,但如果未明确取消链接,它们可能会继续占用 space 后备文件系统(通常 tmpfs/shmfs 用于 /dev/shm 在内存中)。
在 FreeBSD 上,可以使用不可移植的 SHM_ANON 标志来自动取消链接。如果您想要这种行为,您可以:
- 使用带有 MAP_ANONYMOUS 标志的 mmap(2) 并通过 fork(2) 共享文件描述符或使用 Unix 域套接字通过 sendmsg(2) 将它们发送到其他进程。
- 使用带有 IPC_RMID 标志的 System V 共享内存,它会在最后一个进程分离内存段后自动销毁它。分离发生在进程终止或调用 shmdt(2) 时。
- 仅使用较新的 Linux memfd_create(2) 系统调用。
问题似乎是关于如何以及何时清理一个或多个进程使用的 POSIX 共享内存,或者可能是关于如何避免共享内存被过早清理。
POSIX 共享内存是在有意类似于常规文件访问的模型上设计的。特别是,
shm_open()
将创建并打开一个新的、持久的 shared-memory object 或简单地打开一个现有的,具体取决于是否已经存在具有指定名称的。- 该区域可以由其他进程打开(因此必须持续存在)直到通过
shm_unlink()
. 取消链接
- 只要任何进程打开共享内存区域,它在取消链接后就会存在,但无法再通过
shm_open()
. 打开
- 通过
mmap()
映射共享内存区域具有在映射就位时保持打开状态的效果,与用于映射它的文件描述符无关
此外,shared-memory 区域的内存映射在大多数方面与常规文件的映射相同。映射是 per-process 属性;它们不会在它们所属的进程终止后继续存在。映射在 fork()
秒内保留(复制)。
在某些系统上,甚至可以通过文件系统访问共享内存区域。除了管理它们的不同功能外,它们与常规文件的最大区别可能是它们不会在重新启动后保留。
因此,您不必担心进程的终止会意外地破坏其他进程正在使用的共享内存区域。另一方面,您可以安排 shared-memory 区域自动清理,方法是在每个需要按名称获取访问权限的进程完成后取消链接。如果您打算仅授予 child 进程(以及他们的 children 等)的访问权限,那么您可以在创建后立即取消链接。 Children 将在您分叉它们时继承映射。
因此,针对实际问题:
Is this also the case for shared memory objects, are they also closed and unmapped or simply just closed?
进程终止时,进程打开和/或映射的共享内存 object 将同时关闭和取消映射,但它们不会自动取消链接。它们至少会持续存在,直到手动取消链接或系统重新启动。