欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Linux下多線(xiàn)程程序調試方法

多線(xiàn)程程序可能存在很多潛在的bug,如data race,dead lock,信號bug等,而這些bug一向很難調試,現在有很多論文都是基于多線(xiàn)程程序的調試技術(shù)的,比如model check,死鎖檢測,replay技術(shù)等,也有很多對應的工具,如intel的pinplay,微軟的Zing等。關(guān)于這些技術(shù)和工具,如果感興趣可以 google相應的論文進(jìn)一步了解。這里我主要講述的是我在對二進(jìn)制翻譯下多線(xiàn)程程序調試中經(jīng)常使用的一些方法以及一些調試經(jīng)驗,雖然我的調試的是二進(jìn)制翻譯器,但是這些方法也同樣適用于大多數多線(xiàn)程程序。

1、最直接的方法就是在源程序插入printf語(yǔ)句來(lái)打印出一些有用的變量。這種方法的優(yōu)點(diǎn)是不用借助其他工具就可以對程序的運行進(jìn)行觀(guān)察,缺點(diǎn)是插入語(yǔ)句的位置、粒度等都需要調試者自己去權衡,如果插入過(guò)多的打印語(yǔ)句,則頻繁的IO操作會(huì )使程序運行變慢,線(xiàn)程行為改變,有些bug甚至不會(huì )再出現。至于需要在什么地方插入語(yǔ)句,首先,只打印有必要的變量,一個(gè)語(yǔ)句可以打印多個(gè)變量;其次,在循環(huán)中,我們可以通過(guò)設置一些條件來(lái)降低打印的粒度,比如下面這段代碼:

1            2            3            4            5            6            7            8            
while(flag){            pc = getpc();            printf(“pc is:0x%x\n”, pc);//我們插入的打印語(yǔ)句                         ......                         ...... //do somthing using pc;                }

假設我們對pc的取值很感興趣,需要打印出所有pc取到過(guò)的值,但是大多數情況下,getpc()的返回值都同上一次的返回值相同,這樣我們printf出來(lái)的就會(huì )有很多重復值。這種情況下我們可以用下面這種插樁方式來(lái)去處重復值:

1            2            3            4            5            6            7            8            9            10            11            
int  lastpc; //定義為全局變量或局部靜態(tài)變量                         while(flag){            pc = getpc();            if(pc !=lastpc){            lastpc = pc;            printf(“pc is:0x%x\n”, pc);            }            ......            ......//do somthing using pc            }

這樣通過(guò)一個(gè)簡(jiǎn)單的判斷就可以省掉很多沒(méi)有必要的輸出。很多別的情形,比如我們只關(guān)心某一變量等于特定值(比如0)時(shí)其他變量的狀態(tài),我們就沒(méi)有必要把改變量不等于0時(shí)的狀態(tài)打印出來(lái)??傊?,能省則省,只打印我們需要的。

2、利用gdb的attach功能和sleep()函數。gdb是由gnu維護的功能強大的調試工具,并且支持多線(xiàn)程程序的調試,可以在gdb下直接運行一個(gè)多線(xiàn)程程序,通過(guò)thread等命令進(jìn)行調試。但是很多多線(xiàn)程程序在其他工具(gdb,pin,strace等)監管下,原有的bug就不會(huì )出現。這的確是很讓人頭疼的事情,也是我十分不喜歡這個(gè)方法的原因,想象一下,一個(gè)程序直接跑就出錯,但是放到gdb下就能得到正確的結果,好像故意在耍我們一樣。我更喜歡使用gdb的attach功能,我們可以通過(guò)下面的命令來(lái)讓gdb接管一個(gè)運行的線(xiàn)程:

1            
gdb attach <pid>

這種方法的好處是能夠使gdb對程序執行的影響最小,而且可以只接管程序中某一條我們所關(guān)心的線(xiàn)程,而其他線(xiàn)程不受影響。
這時(shí)有人會(huì )問(wèn),如果線(xiàn)程執行過(guò)快,我們還沒(méi)來(lái)得及attach線(xiàn)程就已經(jīng)執行完或者dump掉了,這種情況該怎么辦?解決方法很簡(jiǎn)單,既然線(xiàn)程執行過(guò)快,我們就讓它等一等,可以在源代碼中讓我們關(guān)心這個(gè)線(xiàn)程sleep()一小會(huì )兒,這樣我們就有足夠的時(shí)間來(lái)attach它,并且attach的位置我們也可以進(jìn)行控制,想在哪里attach,就在哪里sleep。

3、第三種方法是利用信號處理函數來(lái)獲取一些信息。在多線(xiàn)程程序的壓力測試中,很多錯誤要每隔幾百幾千次運行才能出現一次,而這種錯誤的replay是很困難的,因此捕捉到這種錯誤的現場(chǎng)很重要。這里我習慣利用信號處理程序來(lái)保存這樣的現場(chǎng),這樣你可以晚上寫(xiě)個(gè)腳本讓程序無(wú)限跑,早上起來(lái)你會(huì )發(fā)現程序停在出錯的地方,這是很愜意的事情。
多數多線(xiàn)程程序出錯,都是訪(fǎng)問(wèn)非法內存,也就是我們常說(shuō)的“段錯誤”(segmentation fault),程序發(fā)生非法內存的訪(fǎng)問(wèn),系統會(huì )發(fā)給線(xiàn)程一個(gè)SIGSEGV信號,這個(gè)信號默認處理為core掉該線(xiàn)程。我們可以對這個(gè)信號進(jìn)行利用,為其注冊一個(gè)信號處理函數:

1            2            3            4            
struct sigaction act;            act.sa_flags = SA_SIGINFO;            act.sa_sigaction = signal_handler;            sigaction(SIGSEGV, &act, NULL); //SIGSEGV表示該信號的值

信號處理函數如下:

1            2            3            4            5            6            7            8            9            10            11            12            13            14            
void signal_handler(int host_signum, siginfo_t *info,                         void *puc){                         struct ucontext *uc = (struct ucontext *)puc;                         int loopflag = 1;                         while(loopflag)        //可以在gdb中手動(dòng)更改loopflag的值跳出循環(huán)                         sleep(1);                         ...... //這里可以打印一些感興趣的變量            }

函數參數中,puc是一個(gè)體系結構相關(guān)的指針,不同的體系結構,指針指向的結構不一樣,里面存放了發(fā)生信號時(shí)線(xiàn)程的寄存器的值,程序地址等信息,函數內第一句話(huà)的目的就是把void類(lèi)型轉換成ucontext結構類(lèi)型,這樣在gdb中可以直接print出該結構的成員。
函數中sleep的作用是讓程序停在信號處理程序中,以給我們足夠的時(shí)間進(jìn)行attach。如果想讓程序繼續運行下去,手動(dòng)把loopflag修改為1即可。用while循環(huán)的目的是我們可以在運行時(shí)手動(dòng)控制sleep的時(shí)間。
這種方法同樣適用于其他信號帶來(lái)的bug,比如SIGBUS等。在二進(jìn)制翻譯下,還可以使用這種方法對二進(jìn)制翻譯器信號處理進(jìn)行跟蹤和調試,具體使用讀者可以自己去發(fā)掘。

4、利用strace得到我們關(guān)心的信息。大多數情況下我們用strace的目的是跟蹤系統調用,但其實(shí)strace對多線(xiàn)程程序的調試有很大的幫助,使用strace打印多線(xiàn)程程序信息的命令如下:

1            
strace -F ./test

如果我們對某些系統調用,如gettimeofday,ioctl不感興趣,可以屏蔽掉

1            
strace -F -etrace=\!gettimeofday,ioctl ./test

通過(guò)strace打印出的信息,我們可以對什么時(shí)候產(chǎn)生了一個(gè)子線(xiàn)程,那個(gè)線(xiàn)程在等待,哪個(gè)線(xiàn)程被喚醒,哪個(gè)線(xiàn)程收到信號,哪個(gè)線(xiàn)程core掉有一個(gè)綜合的了解,這些信息對多線(xiàn)程調試會(huì )起到很大的作用。

還有很多方法比如利用core文件等,很多地方可以查到,我不做累贅的介紹??傊夹g(shù)是死的,但是方法是靈活的,當傳統方法解決不了一個(gè)問(wèn)題的時(shí)候,可以放開(kāi)思路嘗試其他的方法。
如果有任何問(wèn)題,歡迎大家留言和我進(jìn)行討論,我會(huì )在第一時(shí)間進(jìn)行回復。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
gdb調試多進(jìn)程與多線(xiàn)程
gdb調試技巧
gdb和dbx
gdb調試
可重入、異步信號安全和線(xiàn)程安全(一)
使用gdb
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久