У меня проблема с тем, что я не могу правильно закрыть mmap-ы в Python после того, как создал указатель на них.Мой пример использования: я открываю файлы (обычно это 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
Я провел некоторый анализ (используя gc.get_referrers) того, что ссылается на map
-экземпляр, и получается, что 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?