读取只读的mmap对象的地址

7
我目前正在处理一些代码,使用mmap对象在进程之间共享一些状态。用例是一堆进程可以访问共享mmap支持的只读数据中的一些数据。其中一部分涉及对底层内存表示进行一些算术运算,我像这个问题中一样使用ctypes来获取底层内存地址。
我遇到了这样的情况:希望能够以只读方式打开此mmap文件,并且只有读取数据的进程才能打开。但是,当我这样做时,我不确定如何在该情况下获取指针地址。以下是我能够制作的最小示例:
import mmap
import ctypes

filename = "test"

with open(filename, 'rb+') as fd:
    buf = mmap.mmap(fd.fileno(), 0)
    int_pointer = ctypes.c_int.from_buffer(buf)

with open(filename, 'rb') as fd:
    test_mmap_ro = mmap.mmap(
        fd.fileno(), 0, access=mmap.ACCESS_READ,
        )
    int_pointer2 = ctypes.c_int.from_buffer(test_mmap_ro) #fails here

在Python3上运行,会出现以下错误:
TypeError: must be read-write buffer, not mmap.mmap

Python2给出了这个:
TypeError: mmap can't modify a readonly memory map.

考虑到我实际上想使用只读内存映射,我该如何做到这一点?如果必须更改为可写的mmap,则我会更改,但如果有其他方法可以实现这一点,我宁愿不更改,因此任何建议或解决方法都将不胜感激。


我认为值得一提的是,因为我已经在这个项目中使用了CFFI,所以我对利用它的某种解决方案持开放态度。 - shuttle87
"其中一部分涉及对底层内存表示进行一些算术运算" -- 为什么需要绝对地址?你能举个例子吗? - Jashandeep Sohi
假设您有一些 C 代码,它打开 mmap 并将一些结构体写入其中。为了在 Python 中访问该数据,您可能需要能够以单个字节的级别找到该结构体的偏移量。 - shuttle87
你不能直接切片mmap对象吗?-- 当我使用Python解析二进制数据时,通常只需在mmap的子区域上调用ctypes.Structure子类的from_buffer_copy()方法。 - Jashandeep Sohi
2个回答

6

使用 ctypes,我得到了以下代码:

obj = ctypes.py_object(buf)
address = ctypes.c_void_p()
length = ctypes.c_ssize_t()
ctypes.pythonapi.PyObject_AsReadBuffer(obj, ctypes.byref(address), ctypes.byref(length))
int_pointer = address.value

0
为了获得指向只读内存映射(mmap.mmap实例)的char*指针,以便将其传递给C函数,关键是使用CFFI的ffi.from_buffer()(docs)
因此,如果您已经有:
import mmap
with open("my_huge_file.bin", "rb") as stream:
    buf = mmap.mmap(stream.fileno(), 0, access=mmap.ACCESS_READ)

要通过CFFI调用C函数并传递指向映射内存的指针,请按以下方式操作:
from ._my_cffi_module import lib as my_cffi_module, ffi
cbuf = ffi.from_buffer(buf)
my_cffi_module.my_c_function(cbuf, 1, 2, 3)  # Whatever your parameters may be

现在,您的C函数可以自由地从缓冲区中读取数据,使用任何指针算术运算,但当然不能对其进行写入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接