2009-09-21 6 views
35

Powiedz, że mam dwa programy o nazwie bla i ret. Chcę debugować program blah, który odbiera dane wejściowe od ret programu poprzez przekierowanie I/O. Jak mogę debugować program blah w następującym przypadku, używając gdb?gdb - debugowanie z rurą

+0

Czy różni się to od: http://stackoverflow.com/questions/4521015/how-to-pass-arguments-and-redirect-stdin-from-a-file-to-program-run-in-gdb –

Odpowiedz

41

Na początku można uruchomić program i debugować go przez pid. To rozwiązanie oczywiście nie obejmuje wszystkich przypadków.

Innym podejściem jest wykorzystanie możliwości systemu Linux do komunikacji między procesami. W skrócie, przekierowujesz wyjście ret do specjalnego pliku FIFO ("nazwany potok"), a następnie odczytujemy z niego FIFO za pomocą debuggera. Oto, jak to się robi. Z bash, wykonaj:

mkfifo foo 

To tworzy specjalny plik w katalogu, który będzie służył jako nazwanego potoku. Kiedy piszesz tekst do tego pliku (używając tej samej składni echo "Hello" >foo), program piszący będzie blokował, dopóki ktoś nie odczyta danych z pliku (na przykład cat <foo). W naszym przypadku z tego pliku zostanie odczytany proces kontrolowany przez gdb.

Po utworzeniu fifo, uruchom z basha:

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

Następnie w wierszu gdb, uruchom

run <foo 

i uzyskać pożądany efekt. Zauważ, że nie możesz odczytać danych z fifo (jak również z normalnej rury) dwa razy: po przeczytaniu wszystkich danych, proces blah umiera i powinieneś powtórzyć pisanie polecenia do foo (możesz to zrobić z drugiego okna powłoki).

Kiedy skończysz, usuń FIFO z rm foo (lub umieścić go w katalogu, w którym zostanie on automatycznie usunięty po ponownym uruchomieniu systemu, takich jak /tmp).

+1

Jeśli możesz sobie pozwolić na miejsce na dysku, możesz również po prostu włożyć je do zwykłego pliku 'foo', zamiast FIFO' foo' (oszczędza ci jedno polecenie :). – Frank

+7

Zwykłe pliki i pliki FIFO/pipe mają inną semantykę dla read(). Jeśli osiągniesz EOF w zwykłym pliku, read() zwraca z może mniejszą ilością bajtów odczytanych niż określone. Jeśli czytasz z FIFO/pipe, read() blokuje dopóki nie nadejdzie określona liczba bajtów lub nie zakończy się proces zapisu do potoku. – SzG

9

Polecenie GDB run używa bash do wykonywania przekierowania. Prostym sposobem uzyskania odpowiednika ret | blah jest użycie funkcji bash'a o nazwie process substitution.

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

Objaśnienie: bash zastępuje <(ret) z czymś /dev/fd/123, który jest deskryptor pliku na standardowe wyjście z ret. Możemy użyć tego fd podobnie do nazwanego FIFO, jak opisano w drugiej odpowiedzi, z tym że nie musimy ręcznie tworzyć go samodzielnie, ani martwić się o czas trwania procesu ret.

+0

Dokładnie pasuje do moich potrzeb, dzięki. – Limeth

+0

To nie działa dla Zsh. Czy istnieje alternatywa? – redfast00

+0

Podstawienie procesu działa tak samo w zsh, jak w bashu. Jakie jest twoje wywołanie i jaki komunikat o błędzie napotykasz? –