在Python中正确丢弃指向mmap内存的ctypes指针

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

我遇到的问题是,在创建指向 mmap-s 的指针后,我无法在 Python 中正确关闭 mmap-s。我的用例是打开文件(通常是与硬件一起工作的 UIO 设备,但普通文件也会出现此问题),对它们进行内存映射,然后将它们用作 ctypes 结构的缓冲区。通常是数据结构或数组。一个最小的例子如下所示:

import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here

del memory
map.close()
os.close(fileno)

那时一切都很好。

但是,有时我需要调用一些也需要访问该内存的 C 库函数,因此我必须传入指向它们的指针。我使用以下方法创建该指针:

ptr = ct.cast(memory, ct.c_void_p)

除了一件事之外,所有这些都非常有效。一旦我创建了这样的指针,我就无法再关闭内存映射。举这个稍微扩展的例子:

import ctypes as ct
import mmap
import os

fileno = os.open('/tmp/testfile', os.O_RDWR | os.O_SYNC)
map = mmap.mmap(fileno, 32768, flags=mmap.MAP_SHARED)
memory = (ct.c_uint32 * 8192).from_buffer(map)

# Use the memory object to do things here
ptr = ct.cast(memory, ct.c_void_p)
del ptr

del memory
map.close()
os.close(fileno)

运行此命令会导致以下异常:

Traceback (most recent call last):
  File "pointer_test.py", line 14, in <module>
    map.close()
BufferError: cannot close exported pointers exist

Process finished with exit code 1

我对引用

map
实例的内容进行了一些分析(使用 gc.get_referrers),结果发现仍然存在一个
memoryview
实例。最后,这追溯到 ctypes 数组:

[<__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
 [{547965620704: <__main__.c_uint_Array_8192 object at 0x7f954bd1e0>,
   'ffffffff': <memory at 0x7f95621a08>},
  [<memory at 0x7f95621a08>,
   [<managedbuffer object at 0x7f95746d08>,

然而,这并没有真正帮助我。我想知道如何摆脱该指针。我知道这可能并不完全安全,因为当然,我总是可以在某个地方拥有该指针的副本。但在创建指针后完全阻止关闭

mmap
似乎也不是一个好主意。任何人都知道我如何说服 Python 我丢弃了所有指针并且现在可以安全地关闭 mmap 了?

python pointers ctypes mmap memoryview
2个回答
0
投票

找到memoryview实例,先调用

memoryview-instance.release()
,然后就可以关闭mmap实例了。


0
投票

使用

addressof
清洗参考;即
ptr = ct.cast(ct.addressof(memory), ct.c_void_p)

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