我正在研究多处理Python模块来保护一些需要原子访问(做一些事情)的硬件(内存映射)资源。 (硬件是实现某种有限状态机的 FPGA,并且该机器应该在任何其他访问开始之前返回到空闲状态...)
可能想要访问此资源的软件作为不同的 Linux 进程运行,用 Python 编写,其中一些使用线程(因此使用线程模块)。 这些进程不是从常见的 python 父进程生成的:它们通常作为守护进程运行,也从命令行界面运行。
在 C 世界中,我通常会使用名为 semaphore 的 Linux 来保证我的硬件的原子性。我从多处理模块文档中无法完全理解是否可以实现等效功能(以及如何实现)。或者多重处理是否只处理从一个公共单个程序生成(分叉)的进程的锁,该程序在分叉之前创建了锁......
所以问题是,多处理模块是否可以用来处理不相关(即没有任何共同的 python 祖先)进程之间的同步,就像 Linux 中名为 semaphore 的那样?如果是这样,如何...如果不是,最好的选择是什么...
这是一个如何使用命名管道 (FIFO) 来控制多个进程的流程的示例。
在这种情况下,进程共享一个共同的祖先,但这并不重要。访问命名管道的进程可以有不同的父进程。
这里我们创建了 FIFO 并启动了两个进程。每个进程都需要能够从 FIFO 读取一个字节才能继续其工作。
注意 FIFO 必须是无缓冲的,因此也必须处于二进制模式(不能有无缓冲的文本模式)。
在这种情况下,两个子流程是相同的。他们打开 FIFO 并尝试读取一个(未缓冲的)字节。如果 FIFO 仍然打开但为空,则读取将无限期阻塞。
from multiprocessing import Process
from os import mkfifo, unlink, getpid, path
from tempfile import gettempdir
FIFO = path.join(gettempdir(), "_fifo_")
def target():
with open(FIFO, "rb", 0) as fifo:
print(fifo.read(1))
print(getpid(), "Done")
if __name__ == "__main__":
try:
mkfifo(FIFO)
(proc1 := Process(target=target)).start()
(proc2 := Process(target=target)).start()
with open(FIFO, "wb", 0) as fifo:
fifo.write(b"12")
proc1.join()
proc2.join()
finally:
unlink(FIFO)
输出:
b'1'
b'2'
3181 Done
3182 Done