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

时间:2018-11-16 14:38:10

标签: python pointers ctypes mmap memoryview

我有一个问题,在创建指向它们的指针后,我无法在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 Array:

[<__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了。

1 个答案:

答案 0 :(得分:0)

找到memoryview实例并首先调用memoryview-instance.release(),然后您可以关闭mmap实例。