日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

用GDB調(diào)試多進程程序

 楚暮四 2010-05-08

眾所周知,GDB是Unix/Linux下調(diào)試程序的龍頭老大,GDB功能強大,我們在平時多使用其一些 最基本的功能,而且一般調(diào)試的都是單進程的程序。最近一個項目中的問題讓我接觸如何使用GDB調(diào)試多進程程序,更確切的是說調(diào)試調(diào)用fork的多進程程 序。

使用GDB最好的文檔就是其名為'Debugging with GDB' 的參考手冊。手冊中有一小章節(jié)提到了如何調(diào)試多進程程序。一般情況下,如果被gdb調(diào)試的程序中調(diào)用fork派生出一個新的子進程,這時gdb調(diào)試的仍然 還是父進程,其子進程的執(zhí)行不被理會。如果之前你在子進程的執(zhí)行routine上設(shè)置了斷點,那么當(dāng)子進程執(zhí)行到那個斷點時,子進程會因為收到一個 SIGTRAP信號而自行終止,除非你在子進程中攔截了該信號。

那么使用GDB該如何調(diào)試多進程程序呢?在其參考手冊中提供了一種通用方法,這里說說(GDB在某些平臺上如HP-UX,還提供了更簡便的方法,不過不具備通用性,這里不說):

[測試程序]
我們先看看我們的測試程序:
/* in eg1.c */

int wib(int no1, int no2)
{
        int result, diff;
        diff = no1 - no2;
        result = no1 / diff;
        return result;
}

int main()
{
        pid_t   pid;

        pid = fork();
        if (pid <0) {
                printf("fork err\n");
                exit(-1);
        } else if (pid == 0) {
                /* in child process */
                sleep(60); ------------------ (!)

                int     value   = 10;
                int     div     = 6;
                int     total   = 0;
                int     i       = 0;
                int     result  = 0;

                for (i = 0; i < 10; i++) {
                        result = wib(value, div);
                        total += result;
                        div++;
                        value--;
                }

                printf("%d wibed by %d equals %d\n", value, div, total);
                exit(0);
        } else {
                /* in parent process */
                sleep(4);
                wait(-1);
                exit(0);
        }
}
該測試程序中子進程運行過程中會在wib函數(shù)中出現(xiàn)一個'除0'異常?,F(xiàn)在我們就要調(diào)試該子進程。

[調(diào)試原理]
不知道大家發(fā)現(xiàn)沒有,在(!)處在我們的測試程序在父進程fork后,子進程調(diào)用sleep睡了60秒。這就是關(guān)鍵,這個 sleep本來是不該存在于子進程代碼中的,而是而了使用GDB調(diào)試后加入的,它是我們調(diào)試的一個關(guān)鍵點。為什么要讓子進程剛剛運行就開始sleep呢? 因為我們要在子進程睡眠期間,利用shell命令獲取其process id,然后再利用gdb調(diào)試外部進程的方法attach到該process id上,調(diào)試該進程。

[調(diào)試過程]
我覺上面的調(diào)試原理的思路已經(jīng)很清晰了,剩下的就是如何操作的問題了。我們來實踐一次吧!
我所使用的環(huán)境是Solaris OS 9.0/GCC 3.2/GDB 6.1。

GDB調(diào)試程序的前提條件就是你編譯程序時必須加入調(diào)試符號信息,即使用'-g'編譯選項。首先編譯我們的源程序'gcc -g -o eg1 eg1.c'。編譯好之后,我們就有了我們的調(diào)試目標(biāo)eg1。由于我們在調(diào)試過程中需要多個工具配合,所以你最好多打開幾個終端窗口,另外一點需要注意的 是最好在eg1的working directory下執(zhí)行g(shù)db程序,否則gdb回提示'No symbol table is loaded'。你還得手工load symbol table。好了,下面我們就'按部就班'的開始調(diào)試我們的eg1。

執(zhí)行eg1:
eg1 &   --- 讓eg1后臺運行吧。

查找進程id:
ps -fu YOUR_USER_NAME

運行g(shù)db:
gdb
(gdb) attach xxxxx  --- xxxxx為利用ps命令獲得的子進程process id
(gdb) stop --- 這點很重要,你需要先暫停那個子進程,然后設(shè)置一些斷點和一些Watch
(gdb) break 37 -- 在result = wib(value, div);這行設(shè)置一個斷點,可以使用list命令察看源代碼
Breakpoint 1 at 0x10808: file eg1.c, line 37.
(gdb) continue
Continuing.

Breakpoint 1, main () at eg1.c:37
37                              result = wib(value, div);
(gdb) step
wib (no1=10, no2=6) at eg1.c:13
13              diff = no1 - no2;
(gdb) continue
Continuing.

Breakpoint 1, main () at eg1.c:37
37                              result = wib(value, div);
(gdb) step
wib (no1=9, no2=7) at eg1.c:13
13              diff = no1 - no2;
(gdb) continue
Continuing.

Breakpoint 1, main () at eg1.c:37
37                              result = wib(value, div);
(gdb) step
wib (no1=8, no2=8) at eg1.c:13
13              diff = no1 - no2;
(gdb) next
14              result = no1 / diff;
(gdb) print diff
$6 = 0        ------- 除數(shù)為0,我們找到罪魁禍?zhǔn)琢恕?br>(gdb) next
Program received signal SIGFPE, Arithmetic exception.
0xff29d830 in .div () from /usr/lib/libc.so.1

至此,我們調(diào)試完畢。

上面僅僅是一個簡單的多進程程序,在我們平時開發(fā)的多進程程序遠遠比這個復(fù)雜,但是調(diào)試基本原理是不變,有一些技巧則需要我們在實踐中慢慢摸索。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多