Python、ctypes和mmap

12

我想知道ctypes包是否可以与mmap进行接口交互。

目前,我的模块使用create_string_buffer分配一个缓冲区,然后使用byref将其传递给库中的mylib.read函数。这个函数会像名字所示的那样,读取数据到缓冲区中。然后我调用file.write(buf.raw)将数据写入磁盘。然而,我的基准测试显示这远非最优解(花费在file.write上的时间最好花费在mylib.read上)。

因此,我想知道ctypes是否可以与mmap进行互操作。给定一个mmap.mmap实例和一个偏移量,如何在地址空间中获得指针(c_void_p)?


Python有一个mmap模块。 - Seth
1
@Seth 我所指的 mmap.mmap 实例来自该模块。我想知道如何让它的实例与 ctypes 进行接口。 - Freddie Witherden
你确定你应该在Python中做这件事吗?低级指针操作更适合使用C或类似语言。编写C模块以与Python良好地接口也不是太难。 - Katriel
抱歉,我误解了。我以为你试图自己编写mmap接口。 - Seth
2个回答

14
一个 mmap 对象 "支持可写缓冲区接口",因此你可以使用 from_buffer 类方法,所有的 ctypes 类都有这个方法,以 mmap 实例作为参数,创建一个 ctypes 对象,就像你想要的那样,即共享 mmap 实例映射的内存(和因此底层文件)。我想,具体来说,你会想要一个合适的 ctypes 数组

2
一个很好的例子:https://github.com/serdardalgic/Code_Snippets/blob/master/Python-Examples/mmap/shared_memory_write.py - Jonathon Reinhart
这样做真的只会导致对mmap的查看,没有行为上的差异吗?(ctypes.c_ubyte * mmap_obj.size()).from_buffer(mmap_obj) 看起来很危险,整个数据可能一次性加载到内存中,而不是惰性加载...? - mara004
这样做真的只会导致对mmap的查看,没有任何行为上的差异吗?(ctypes.c_ubyte * mmap_obj.size()).from_buffer(mmap_obj)看起来很危险,整个数据可能会一次性加载到内存中,而不是懒加载...? - undefined

1
请注意,操作系统将会对read()进行预读取。你将会在read()或write()中阻塞,其中一个将成为瓶颈操作,但即使你在其中一个操作中被阻塞,另一个操作仍然会在后台进行。这是每个多任务操作系统的工作。
如果你使用mmap来实现这个功能,很可能会让操作系统变得更加复杂,因为它难以确定你只是在流式传输数据,并且难以进行预读取。它可能仍然能够解决这个问题(操作系统非常擅长这方面),但你可能没有帮助它。
原则上唯一的好处是避免内存复制的成本,但这似乎不是你的目标(除非性能分析明确表示需要,否则我强烈怀疑这会提高性能)。

2
mylibrary.read() 与连接的1394设备交互,此时系统的I/O总线完全空闲。在询问之前,我使用原始C破解了相同的循环,并对mmap和read()/ write()进行了基准测试。 mmap快了约50%。 - Freddie Witherden

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