linux:如何同时等待进程和文件?

roqulrg3  于 2023-01-12  发布在  Linux
关注(0)|答案(1)|浏览(132)

我尝试在python中建立一个事件循环,主要是为了教学目的,我对涉及asyncio或类似的解决方案不感兴趣,因为我的目标实际上是学习底层的linux API。
对于类似文件的对象(管道,套接字,...),有select/poll/epoll系统调用,在python中,这些被 Package 在selectors module中,这是一个可以同时等待多个文件的简单循环:

file1 = open('/var/run/foo.sock')
file2 = open('/var/run/bar.sock')

with selectors.DefaultSelector() as selector:
    selector.register(file1, selectors.EVENT_READ)
    selector.register(file2, selectors.EVENT_READ)

    while True:
        for key, mask in selector.select():
            if key.fileobj == file1:
                handle_data(file1)
            else:
                handle_data(file2)

对于proceses,有一个wait系统调用,在python中它被 Package 在subprocess module中,这是等待单个进程终止的代码:

proc = subprocess.Popen(['/usr/bin/foo'])
proc.wait()
handle_data(proc)

我如何混合这两个进程,甚至一次等待多个进程。
selector.select()proc.wait()都会超时,所以我们可以将其转换为半忙循环:

file1 = open('/var/run/foo.sock')
file2 = open('/var/run/bar.sock')
proc = subprocess.Popen(['/usr/bin/foo'])
timeout = 1

with selectors.DefaultSelector() as selector:
    selector.register(file1, selectors.EVENT_READ)
    selector.register(file2, selectors.EVENT_READ)

    while True:
        for key, mask in selector.select(timeout):
            if key.fileobj == file1:
                handle_data(file1)
            else:
                handle_data(file2)

        if proc:
            try:
                proc.wait(timeout)
                handle_data(proc)
                proc = None
            except TimeoutExpired:
                pass

我想一定有更好的办法。这通常是怎么做的?

9udxz4iz

9udxz4iz1#

当我在python的asyncio中查看子监视器的不同实现时,我发现了相关的信息:

  • 你可以在一个单独的线程中调用os.waitpid(),并在完成后写入管道,管道的另一端可以添加到select循环中,这种方法似乎是最常用的。
  • 当你接收到SIGCHLD的时候,你可以写一个管道,然后再次把管道的另一端添加到select循环中,然后你可以调用process.poll()来检查哪个进程在O(n)时间内终止了。
  • open_pidfd()正是我要找的。它是最干净的解决方案,但只在Linux〉= 5. 3上可用。如果你不必关心可移植性,这可能是你要走的路。

相关问题