为什么我的共享内存在 MacOS 上读数为零?

问题描述 投票:0回答:1

我正在编写一个接口,以允许用 C 编写的主程序和用 python 编写的扩展脚本之间进行通信,并在单独的 python 解释器进程中运行。该接口使用 UNIX 套接字来处理少量数据,使用 POSIX 共享内存来处理大型数组。 C 程序处理共享内存的所有创建、资源跟踪和最终取消链接。

这在 Linux 上完美运行。我可以使用 shm 按预期在两个进程之间传输数据。

然而,当完全相同的代码在 MacOS 上运行时,尽管它运行时没有错误,但当从另一个进程读取到填充内存的进程时,共享内存总是充满零。例如如果我从 C 将图像数据写入 shm,并从 python 读取它,则全部为零。如果我从 python 将图像数据写入 shm 并从 C 读取它,那么它又全为零。 我在 C 中创建 shm,如下所示:(为了清楚起见,删除了一些错误处理行)

    void *shm_ptr = NULL;
    snprintf(shm_name_ptr, 30, "/%08x%08x%08x%04x", my_random_int(), my_random_int(), my_random_int(), my_random_int());
    debug_print("shm name: %s\n", shm_name_ptr);
    *fd = shm_open(shm_name_ptr, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
    ftruncate(*fd, aligned_size) == -1);
    shm_ptr = mmap(NULL, (size_t) aligned_size, PROT_READ | PROT_WRITE,
                MAP_SHARED, *fd, 0);
    *shm_ptr_ptr = shm_ptr;

然后详细信息通过套接字传递给python。我没有重现它的细节,因为代码相当长,对于 Windows 等使用#ifdefs,但是套接字机制确实有效,我可以打印 shm 名称,因为它是在 C 中创建的,也是在 python 中接收的表明它们是相同的:

shm name: /b6c31655f708d0e20760b60bc483
SHM allocation: Original size: 25941632, Aligned size: 25944064, Page size: 4096
Truncating shm file to 25941632 bytes
log: b'/b6c31655f708d0e20760b60bc483'

(第一行文本是从 C 打印的,最后一行是从 python 打印的。)

我在 python 中使用的包装类中的

__init__
函数来打开 shm,如下所示:

class SharedMemoryWrapper:
    """
    Wrapper class to handle shared memory creation and cleanup across platforms.
    """
    def __init__(self, name: str, size: int):
        self.name = name
        self.size = size  # Store intended size separately
        self._shm = None
        try:
            # First try to attach to existing shared memory
            self._shm = shared_memory.SharedMemory(name=self.name)
            unregister(self._shm._name, "shared_memory")
        except FileNotFoundError:
            # If it doesn't exist, create new shared memory
            print("Existing SHM not found, creating a new one...")
            self._shm = shared_memory.SharedMemory(name=self.name, create=True, size=self.size)

(之所以存在

unregister()
调用,是因为 SHM 始终由 C 程序分配、跟踪和清理,并传递给 python 程序,因此当 python 脚本退出时,这会抑制有关 shm 泄漏的警告消息。)

一旦通过套接字接收到名称和大小,共享内存对象就会使用

SharedMemoryWrapper(name=name_from_socket, size=size_from_socket)

进行初始化

在 Linux 上,try 块有效并且 shm 已正确打开,但是在 MacOS 上,我看到消息“未找到现有 SHM,正在创建一个新的...”

请有人解释一下 MacOS 的不同之处,以及如何修复它以便正确打开现有的 shm?

python c shared-memory
1个回答
0
投票

我是 OP 的同事,已经调查了我们遇到的问题。

在C端创建共享内存对象时,在其名称中使用前导斜杠:

 int fd = shm_open("/mem", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);

在 Python 端访问它时,不要使用前导斜杠,因为它是 在 POSIX 系统上自动添加的

shm = shared_memory.SharedMemory(name="mem", create=False)

现在 Python 能够找到该对象了。

© www.soinside.com 2019 - 2024. All rights reserved.