[英]how to write to shared memory in python from stream?
我有一个来自多个服务器的进程,这些进程每秒通过udp将数据发送到本地端口2222。
我想读取此数据并将其写入共享内存,以便可以有其他进程从共享内存中读取数据并对其进行处理。
我一直在阅读有关mmap
,看来我必须使用一个文件...我似乎无法理解为什么。
我有一个从套接字读取数据的a.py
,但是如何将其写入shm?
一旦编写完成,我需要编写b.py
, c.py
, d.py
等,以读取相同的shm并对其进行处理。
任何帮助或代码片段都将大有帮助。
首先,请注意,您要构建的内容将不仅需要共享内存:如果a.py
向共享内存写入内容就很好了,但是b.py
如何知道何时准备好内存并可以从中读取内容呢? 总而言之,通过不通过共享内存而是通过某种其他机制连接多个进程,通常可以更轻松地解决此问题。
( mmap
之所以通常需要一个文件名的原因是,它需要一个名称来连接多个进程。的确,如果a.py
和b.py
都调用mmap()
,系统将如何知道这两个进程在询问对于他们,而不是一些无关之间共享内存z.py
呢?因为他们都mmap
编在同一个文件有,也是Linux特定的扩展,得到不对应于文件名的名称,但它更是一个入侵恕我直言。)
也许最基本的替代机制是管道:它们通常在启动程序时借助Shell进行连接。 这就是下面的工作方式(在Linux / Unix上): python a.py | python b.py
python a.py | python b.py
a.py
发送的任何输出a.py
将进入管道,管道的另一端是b.py
的输入。 您将编写一个a.py
以便它侦听UDP套接字并将数据写入stdout,以及一个b.py
以便它从stdin读取以处理接收到的数据。 如果数据需要去几个过程,你可以使用如命名管道,它有一个很好的(但猛砸专用)语法: python a.py >(python b.py) >(python c.py)
将启动a.py
有两个参数,它们是可以打开和写入的伪文件的名称。 写入第一个伪文件的内容将作为b.py
输入,类似地,写入第二个伪文件的内容将作为c.py
输入。
mmap
不需要文件名,而是文件描述符。 它执行所谓的内存映射,即,将进程的虚拟内存空间中的页面与文件描述符所表示的文件状对象的各个部分相关联。 这是一项非常强大的操作,因为它允许您:
POSIX之前在Unix上使用共享内存的旧方法是使用System V IPC共享内存。 首先必须使用shmget(2)
创建一个共享内存段,然后使用shmat(2)
将其附加到进程中。 SysV共享内存段(以及其他IPC对象)没有名称而是数字ID,因此提供了特殊的哈希函数ftok(3)
,该函数将路径名字符串和项目ID整数的组合转换为数字键ID ,但可能发生碰撞。
使用共享内存的现代POSIX方法是使用shm_open(2)
打开类似文件的内存对象,使用ftruncate(2)
将其调整为所需的大小,然后对其进行mmap(2)
。 在这种情况下,内存映射的行为就像是从SysV IPC API调用shmat(2)
一样,由于shm_open(2)
创建的初始大小为零,因此必须进行截断。
(它们是C API的一部分; Python模块提供的功能或多或少地围绕着这些调用进行了精简包装,并且通常具有几乎相同的签名)
也可以通过在所有需要共享内存的进程中通过内存映射相同的常规文件来获取共享内存。 实际上,Linux通过在特殊的tmpfs
文件系统上创建文件来实现POSIX共享内存操作。 通过直接将保存文件内容的页面映射到执行mmap(2)
的进程的地址空间中, tmpfs
驱动程序实现了非常轻量级的内存映射。 由于tmpfs
行为与普通文件系统相同,因此您可以使用ls
, cat
和其他shell工具检查其内容。 您甚至可以通过这种方式创建共享内存对象,或者修改现有对象的内容。 tmpfs
的文件与常规文件系统文件之间的区别在于,后者会持久存储到存储介质(硬盘,网络存储,闪存驱动器等)中,并且偶尔会有更改刷新到该存储介质,而前者完全位于RAM中。 Solaris还提供了类似的基于RAM的文件系统,也称为tmpfs
。
在现代操作系统中,内存映射被广泛使用。 可执行文件是内存映射的,以便提供那些包含可执行代码和静态数据的页面的内容。 共享库也映射到内存。 由于共享了这些映射,因此节省了物理内存,例如,在每个进程的虚拟内存空间中映射了包含可执行文件或共享库内容的相同物理内存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.