1.在linux系統中,程序狀態除了我們所熟知的task_running,task_interruptible,task_stopped等,還有乙個task_traced。這表明這個程序處於什麼狀態?
2.strace可以方便的幫助我們
記錄程序所執行的系統呼叫
,它是如何跟蹤到程序執行的?
3.gdb是我們除錯程式的利器,可以設定斷點,單步跟蹤程式。它的實現原理又是什麼?
所有這一切的背後都隱藏著linux所提供的乙個強大的
系統呼叫ptrace()
. 1.ptrace系統呼叫
ptrace系統調從名字上看是用於程序跟蹤的,它提供了
父程序可以觀察和控制其子程序執行的能力
,並允許父程序檢查和替換子程序的核心映象(包 括暫存器)的值。其基本原理是: 當使用了ptrace跟蹤後,
所有傳送給被跟蹤的子程序的訊號(除了sigkill),都會被**給父程序,而子程序則會被阻塞,這時子程序的狀態就會被 系統標註為task_traced
。而父程序收到訊號後,就可以對停止下來的子程序進行檢查和修改,然後讓子程序繼續執行。
其原型為:
[cpp]view plain
copy
print?
#include
long
ptrace(
enum
__ptrace_request request, pid_t pid,
void
*addr,
void
*data);
ptrace有四個引數:
1). enum __ptrace_request request:指示了ptrace要執行的命令。
2). pid_t pid: 指示ptrace要跟蹤的程序。
3). void *addr: 指示要監控的記憶體位址。
4). void *data: 存放讀取出的或者要寫入的資料。
ptrace是如此的強大,以至於有很多大家所常用的工具都基於ptrace來實現,如strace和gdb。接下來,我們借由對strace和gdb的實現,來看看ptrace是如何使用的。
2. strace的實現
strace常常被用來攔截和記錄程序所執行的系統呼叫,以及程序所收到的訊號。如有這麼一段程式:
helloworld.c:
[cpp]view plain
copy
print?
#include
intmain()
編譯後,用strace跟蹤: strace ./helloworld
可以看到形如:
execve("./helloworld", ["./helloworld"], [/* 67 vars */]) = 0
brk(0) = 0x804a000
mmap2(null, 4096, prot_read|prot_write, map_private|map_anonymous, -1, 0) = 0xb7f18000
access("/etc/ld.so.preload", r_ok) = -1 enoent (no such file or directory)
open("/home/supperman/workspace/lib/tls/i686/sse2/libc.so.6", o_rdonly) = -1 enoent (no such file or directory)
...
的一段輸出,這就是在執行helloworld中,系統所執行的系統呼叫,以及他們的返回值。
下面我們用ptrace來研究一下它是怎麼實現的。
...
[cpp]view plain
copy
print?
switch
(pid = fork())
else
//第二次(退出系統呼叫),獲取系統呼叫的返回值
ptrace(ptrace_syscall,pid,null,null);
}
}
...
在上面的程式中,fork出的子程序先呼叫了ptrace(ptrace_traceme)表示子程序讓父程序跟蹤自己。然後子程序呼叫 execl載入執行了helloworld。而在父程序中則使用wait系統呼叫等待子程序的狀態改變。子程序因為設定了ptrace_traceme而 在執行系統呼叫被系統停止(設定為task_traced),這時父程序被喚醒,使用ptrace(ptrace_peekuser,pid,...)分 別去讀取子程序執行的系統呼叫id(放在orig_eax中)以及系統呼叫返回時的值(放在eax中)。然後使用ptrace (ptrace_syscall,pid,...)指示子程序執行到下一次執行系統呼叫的時候(進入或者退出),直到子程序退出為止。
程式的執行結果如下:
process executed system call id = 11
process executed system call id = 45 with return value= 134520832
process executed system call id = 192 with return value= -1208934400
process executed system call id = 33 with return value= -2
process executed system call id = 5 with return value= -2
...
其中,11號系統呼叫就是execve,45號是brk,192是mmap2,33是access,5是open...經過比對可以發現,和 strace的輸出結果一樣。當然strace進行了更詳盡和完善的處理,我們這裡只是揭示其原理,感興趣的同學可以去研究一下strace的實現。
ps:
1). 在系統呼叫執行的時候,會執行pushl %eax # 儲存系統呼叫號orig_eax在程式使用者棧中。
2). 在系統呼叫返回的時候,會執行movl %eax,eax(%esp)將系統呼叫的返回值放入暫存器%eax中。
3). wifexited()巨集用來判斷子程序是否為正常退出的,如果是,它會返回乙個非零值。
4). 被跟蹤的程式在進入或者退出某次系統呼叫的時候都會觸發乙個sigtrap訊號,而被父程序捕獲。
5). execve()系統呼叫執行成功的時候並沒有返回值,因為它開始執行一段新的程式,並沒有"返回"的概念。失敗的時候會返回-1。
6). 在父程序進行進行操作的時候,用ps檢視,可以看到子程序的狀態為t,表示子程序處於task_traced狀態。當然為了更具操作性,你可以在父程序中加入sleep()。
除錯PPC裝置上的網路程式
最近在除錯ppc裝置上的網路程式時,總是發現有時可以連線成功,有時則無法連線,多次試驗後發現 當ppc裝置連線到電腦後,原來通過gprs或cdma 1x建立的網路連線會自動中斷,ppc裝置會改為使用pc機的網路進行網路連線,在這種情況下自然是不能測試gprs或cdma 1x網路程式。解決辦法 在pp...
遊承超 手機鋼化玻璃膜平邊與弧邊的區別(1P)
無可否認,現今智慧型手機市場是觸控螢幕的時代,螢幕越來越大,隨之而來的是螢幕容易摔壞的問題。試想如果您的愛機不小心掉地上了,螢幕摔壞了,手機就暫時不能用了。換個觸控螢幕又要很大的費用而且要等很長的一段時間。而貼一張小小的鋼化膜,可以給您的手機帶來多一層保護,如果掉地上,損壞掉的只是一層鋼化膜,而你的...
Linux上的C C 偵錯程式GDB
gnu 的偵錯程式稱為 gdb,該程式是乙個互動式工具,工作在字元模式。在 x window 系統中,有乙個 gdb 的前端圖形工具,稱為 gdb。gdb 是功能強大的除錯程式,可完成如下的除錯任務 設定斷點 監視程式變數的值 程式的單步執行 修改變數的值。在可以使用 gdb 除錯程式之前,必須使用...