2009-09-21 93 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