linux ptrace 内核源码分析,linux 3.5.4 ptrace源码分析分析(系列一)
ptrace是linux系統中為了調試專門設立的一種系統調用。要想調試調試一個進程,有兩種方式:
PTRACE_TRACEME和PTRACE_ATTACH。這兩種方式的主要區別可以概括為:
PTRACE_TRACEME是子進程主動申請被TRACE。而PTRACE_ATTACH是父進程自己要attach到子進程,相當于子進程是被動的trace。
PTRACE_TRACEME程序設置的框架大概為:
if(pid==0)//child
{
ptrace(PTACE_TRACEME,0,NULL,NULL);
exec(...);
}
else//parent
{
wait(&status);
if(WIFSTOPPED(status))
fprintf(stderr,"%s\n",WSTOPSIG(status);//打印出子進程當前的狀態。
}看似簡單的代碼,其實內核做了大量的工作,我們在此進行詳細分析。
當程序執行ptrace系統調用,傳入PTRACE_TRACEME函數時,內核執行下面的代碼段:
static int ptrace_traceme(void)
{
int ret = -EPERM;
write_lock_irq(&tasklist_lock);
/* Are we already being traced? */
if (!current->ptrace) {
ret = security_ptrace_traceme(current->parent);
/*
* Check PF_EXITING to ensure ->real_parent has not passed
* exit_ptrace(). Otherwise we don't report the error but
* pretend ->real_parent untraces us right after return.
*/
if (!ret && !(current->real_parent->flags & PF_EXITING)) {
current->ptrace = PT_PTRACED;
__ptrace_link(current, current->real_parent);
}
}
write_unlock_irq(&tasklist_lock);
return ret;
}從上面的源碼我們可以看出:PTRACE_TRACEME并沒有使子進程停止,而是將進行一系列判斷之后(父進程是否能對子進程進行跟蹤的合法性檢查),將子進程鏈接到父進程的ptrace鏈表中。
真正導致子進程停止的是exec系統調用,該系統調用成功之后,內核會判斷該進程是否被ptrace跟蹤,如果被跟蹤的話,內核將向該進程發送SIGTRAP信號。該信號將導致當前進程停止。具體的代碼如下:
static inline void ptrace_event(int event, unsigned long message)
{
if (unlikely(ptrace_event_enabled(current, event))) {
current->ptrace_message = message;
ptrace_notify((event << 8) | SIGTRAP);
} else if (event == PTRACE_EVENT_EXEC) {
/* legacy EXEC report via SIGTRAP */
if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED)
send_sig(SIGTRAP, current, 0);
}
}我們都知道:SIGTRAP信號是專門為debug設計的,當內核踩中斷點的時候(斷點就是int 3,相應的回調函數就是do_trap),就會發送這個信號:
asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
{
siginfo_t info;
memset(&info, 0, sizeof(info));
info.si_signo = SIGTRAP;
info.si_code = TRAP_TRACE;
info.si_addr = (void *)address;
force_sig_info(SIGTRAP, &info, current);
regs->pc += 4;
}
從這里我們可以看出,進程被trace之后,對于子進程的許多操作(尤其是父進程感興趣的操作)都改變了,目的是為了讓父進程感知到這些事件,exec就是一個例子。
此時,父進程的wait操作將被喚醒。我們知道wait操作就是父進程用來檢測子進程的退出情況,wait操作返回有三種情況:
1、子進程正常退出
int status;
wait(&status);//status保存了子進程當前的狀態
WIFEXITED(status)://如果子進程確實正常退出,則為真
WEXITSTATUS(status)://打印出進程的退出碼
2、子進程因為收到信號而退出
int status;
wait(&status);
WIFSIGNALED(status)://如果子進程確實正常退出,則為真
WTERMSIG(status)://打印出進程的退出碼
3、子進程因為收到信號而暫停
int status;
wait(&status);
WIFSTOPPED(status)://如果子進程確實正常退出,則為真
WSTOPSIG(status)://打印出進程的退出碼 顯然,PTRACE_TRACEME對應的就是第三種情況。如果想要輸出信號對應的描述性字符串,可以這樣操作:
sprintf(stderr,"%s\n",WSTOPSIG(status));
總結
以上是生活随笔為你收集整理的linux ptrace 内核源码分析,linux 3.5.4 ptrace源码分析分析(系列一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 楚乔传阮圣文饰演的贺萧是什么人 结局死了
- 下一篇: suse10 linux安装,SuSE1