【问题标题】:Accessing shared memory in a process after shmdt() and before shmctl(shmid, ipc_RMID, 0)在 shmdt() 之后和 shmctl(shmid, ipc_RMID, 0) 之前访问进程中的共享内存
【发布时间】:2015-05-11 06:17:55
【问题描述】:

假设我有一个指向先前分配的共享内存的指针 *p

如果其中一个进程调用shmdt() 来分离共享内存段,然后尝试分配一个值,例如:

*p = 0;

在调用shmctl(shmid, IPC_RMID, 0) 进行销毁之前。

这样做会导致错误吗?我很难理解是哪一个以及为什么。

【问题讨论】:

    标签: c linux process shared-memory


    【解决方案1】:

    是的,这是一个错误,很可能会导致段错误。

    当您调用shmget(2) 分配共享内存段时,它不会立即放在进程的虚拟地址空间中的任何位置。也就是说,没有可以写入的地址会将数据写入段。

    shmat(2) 的工作是将段放入(映射)到进程的地址空间中。 (在 System V 共享内存用语中,这称为附加段,但该术语在其他地方使用不多。映射更常见。)在成功调用 @ 987654324@,该段将出现在某个地址,并且该地址作为shmat()的结果返回。

    在先前附加的段上调用shmdt(2) 会使该段再次从进程的虚拟地址空间中消失。尝试写入以前属于映射一部分的地址是错误的,因为映射不再存在。然而,这并不意味着写入该段的数据会丢失——它只是没有映射到任何地方。您可以再次调用shmat(2) 重新映射(重新附加)该段以再次访问数据。

    只有在您使用shmctl()IPC_RMID 销毁段之后,才会真正释放内存(一旦段不再附加到任何地方)。

    为了让事情更具体一点,以下是共享内存的简单实现如何在高层次上工作:

    • shmget() 分配的物理内存与您对该段的请求一样多。

    • shmat()MMU 进行编程并在内核中进行设置,以便进程中的某些地址范围映射到该段。

    • shmdt() 执行反向操作并删除映射。

    • shmctl()IPC_RMID 释放段的物理内存(将其标记为空闲)。

    附带说明,可以使用shmat(2) 将同一段映射到地址空间中的多个位置。这是可能的,因为它纯粹是一个虚拟内存操作。

    【讨论】:

    • 感谢您的冗长回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2018-07-06
    • 2012-07-03
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 2021-12-06
    相关资源
    最近更新 更多