日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux ptrace 内核源码分析,linux 3.5.4 ptrace源码分析分析(系列一)

發布時間:2023/12/1 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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源码分析分析(系列一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。