2009-09-21 156 views
35

假设我有两个程序,分别命名为blahret。我想调试嗒嗒程序经由I/O重定向接收从RET程序输入。如何在使用gdb的情况下调试blah程序?gdb - 用管道调试

bash> ret | blah 
+0

这是不同于:http://stackoverflow.com/questions/4521015/how-to-pass-arguments-and-redirect-stdin-from-a-file-to-program-run-in-gdb – 2015-07-02 18:27:34

回答

41

首先,您可以运行该程序并通过pid进行调试。当然,这个解决方案并不涵盖所有情况。

另一种方法是使用进程间通信Linux的能力。简而言之,您将ret的输出重定向到一个FIFO特殊文件(“命名管道”),然后通过调试器从该FIFO中读取。这是如何完成的。从bash中,运行:

mkfifo foo 

这会在你的目录中一个特殊的文件,该文件将作为命名管道。当你写文本文件(使用相同的语法echo "Hello" >foo),写程序将阻塞,直到有人从文件中读取数据(cat <foo,例如)。在我们的例子中,gdb控制的进程将从这个文件中读取。

您创建了一个FIFO,从bash的运行后:

ret > foo & # ampersand because it may block as nobody is reading from foo 
gdb blah 

然后,在gdb提示符下运行

run <foo 

,并得到预期的效果。需要注意的是,你不能从FIFO(以及从通常的管道)读取数据两次:当你读过的所有数据,将blah进程死掉,你应该重复的命令写为foo(你可以做到这一点从另一个shell窗口)。

完成后,使用rm foo删除fifo(或将其放入系统重新启动时将自动删除的目录中,例如/tmp)。

+1

如果你可以负担得起磁盘空间,你也可以将它变成普通文件'foo',而不是FIFO'foo'(节省你一个命令:)。 – Frank 2010-04-20 17:54:27

+7

常规文件和FIFO /管道对于read()具有不同的语义。如果以常规文件到达EOF,则read()返回的读取字节数可能少于指定的字节数。如果您从FIFO /管道读取数据,则读取()将阻塞,直到达到指定的字节数,或写入管道的进程已退出。 – SzG 2012-09-27 09:38:54

9

GDB的run命令使用bash执行重定向。实现相当于ret | blah的简单方法是使用bash的process substitution功能。

$ gdb blah 
... 
(gdb) run < <(ret) 

说明:bash的替代<(ret)喜欢的东西/dev/fd/123,这是ret标准输出的文件描述符。除了我们不必自己手动创建它,也不必担心ret进程的生命周期,我们可以使用该fd与指定的FIFO相似。

+0

正是适合我的需求,谢谢。 – Limeth 2016-12-29 14:38:35

+0

这对zsh不起作用。有其他选择吗? – redfast00 2017-05-04 19:05:43

+0

进程替换在zsh中的作用与在bash中的作用相同。什么是你的调用,你遇到什么错误信息? – 2017-05-05 19:17:32