【问题标题】:Why can I not read from stdin in this forked process?为什么我不能在这个分叉的进程中读取标准输入?
【发布时间】:2012-09-06 20:51:11
【问题描述】:

以下代码不打印任何内容,但它应该重复打印出“a”。 os.read(0, 1) 上的分叉进程阻塞。父进程确实在写入 stdin_master,但 stdin_slave 什么也没收到。有什么想法吗?

import os
import pty
import resource
import select
import signal
import time


stdin_master, stdin_slave = pty.openpty()
stdout_master, stdout_slave = pty.openpty()
stderr_master, stderr_slave = pty.openpty()

pid = os.fork()

# child process
if pid == 0:
    os.setsid()
    os.close(stdin_master)
    os.close(stdout_master)
    os.close(stderr_master)

    os.dup2(stdin_slave, 0)
    os.dup2(stdout_slave, 1)
    os.dup2(stderr_slave, 2)

    max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
    os.closerange(3, max_fd)


    while True:
        char = os.read(0, 1)
        os.write(1, char)

    os._exit(255)

# parent process
else:
    os.close(stdin_slave)
    os.close(stdout_slave)
    os.close(stderr_slave)

    try:
        while True:
            read, write, err = select.select([stdout_master], [stdin_master], [], 0)
            for to_read in read:
                print os.read(to_read, 1)

            for to_write in write:
                os.write(to_write, "a")

            time.sleep(0.1)

    finally:
        os.kill(pid, signal.SIGKILL)

【问题讨论】:

    标签: python fork stdin pty


    【解决方案1】:

    我不确定你想在这里使用pty 模块。您似乎需要的基本上是一对os.pipe

    这是一个使用管道的解决方案:

    import os
    import select
    import signal
    import time
    
    
    stdin_slave, stdout_master = os.pipe()
    stdin_master,stdout_slave  = os.pipe()
    
    pid = os.fork()
    
    # child process
    if pid == 0:
    
        while True:
            char = os.read(stdin_slave, 1)
            os.write(stdout_slave, char)
    
        os._exit(255)
    
    # parent process
    else:
        try:
            while True:
                read, write, err = select.select([stdin_master], [stdout_master], [], 0)
    
                for to_read in read:
                    print os.read(to_read, 1)
    
                for to_write in write:
                    os.write(to_write, "a")
    
                time.sleep(0.1)
    
        finally:
            os.kill(pid, signal.SIGKILL)
    

    【讨论】:

    • 不幸的是,示例代码是需要伪终端的应用程序的简化版本,否则您的回答将是解决我的问题的好方法。
    【解决方案2】:

    Thomas Wouters 很友好地提供了答案:

    只能从主 fd 读取 PTY。因此,孩子的 os.read(0, 1) 因此无法正常工作。如果我们改变

    stdin_master, stdin_slave = pty.openpty()
    

    stdin_slave, stdin_master = pty.openpty()
    

    现在 chlid 将从 master 读取,我们将从 parent 写入 slave。这行得通。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-14
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      相关资源
      最近更新 更多