1

我编写了一个简单的调试器程序,它可以执行控制台程序并将其输出发送到“out”和“err”文件,并从“in”文件中检索其输入。现在,我想扩展它的功能来运行 Python 脚本。为此,我想我可以让调试器只运行 Python 解释器并将 Python 解释器与文件接口。

但是当我在调试器中运行 Python 解释器时,我看不到任何输出,就像使用普通程序一样。调试器有非常详细的错误日志,我在错误日志文件中看不到任何错误。

我使用了“ps -A”,但调试器似乎已经启动了 Python 解释器,原因有两个:1)进程 ID 相差 1 和 2)调试器在我杀死 -9 python 解释器后立即退出(即说明文件描述符已连接)。这是 ps -All 的输出:

1 R     0  1565     1 88  80   0 -  1040 -      pts/0    00:01:45 debugger
0 S     0  1566  1565  0  80   0 -  7782 pipe_w pts/0    00:00:00 python.out

调试器是这样启动的(python.out 是 python 解释器的副本):

debugger python.out

所以我想我的问题是,有谁知道为什么这不起作用?Python 解释器对它的标准文件描述符做了什么奇怪的事情吗?

编辑:

  • 我还注意到 python.out 无法使用 python.out > out_file 重定向其 IO - 这可能与调试器遇到的问题有关,也可能无关。

  • 调试器不使用块缓冲。

  • 以下是来自 /proc/pid/io 的一些 io 信息:

调试器(我将一些长度为 21 的数据写入“in”文件)

rchar: 21
wchar: 21
syscr: 300222462
syscw: 1
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0

Python 解释器

rchar: 517268
wchar: 0
syscr: 93
syscw: 0
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0
4

1 回答 1

2

Python 解释器的pipe_w等待状态是一个赠品:它无法运行,因为它要么试图从空管道读取,要么写入满管道。

在您的代码或解释器或两者中都使用了块缓冲,您还没有向我们展示足够的内容来告诉我们是哪一个。

添加以回应评论:

您认为您不是块缓冲,但 stdio 库可能在您不知情的情况下这样做。考虑简单的:

main()
{
    puts("print ('hello, world!')\n");
    sleep(3600);
}

当您从终端运行它时,它会print ('hello, world!')在终端上打印,然后休眠一个小时,正如您所期望的那样。这是因为 stdio 库检测到这stdout是一个终端,并write()在每个换行符上执行其缓冲区。这样做是因为人们喜欢在行缓冲输出准备好时看到它。但是,如果您将此程序的输出通过管道传输到python,则终端上一小时内不会显示任何内容;这是因为 stdio 库将其视为stdout管道并切换到块缓冲模式。在块缓冲模式下,stdio 将等到它有BUFSIZ要写入的字符并且在现代机器BUFSIZ上为 4096 或更高。

当您说“我可以确认调试器正在读取我传递给它的输入”时,由于 stdio 的这种模式切换,您在终端上测试调试器实际上不会告诉您进程间通信是否被缓冲. 的输出ps表明它正在缓冲。请参阅setvbuf了解如何控制缓冲。

或者你可以显示你的代码而不是 useless /proc/n/io。我的python报告:

rchar: 288789
wchar: 0
syscr: 108
syscw: 0
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0

但它仍然没有给出任何输出,直到时间到了,因为它/proc/n/wchan

pipe_wait

正如预期的那样。

于 2013-05-05T01:10:44.930 回答