- 在上一次的Linux系統(tǒng)調(diào)用窺探介紹中,我選取了sys_getpid這個(gè)系統(tǒng)調(diào)用,這個(gè)系統(tǒng)調(diào)用比較簡單,調(diào)用號0X14,除此之外不需要額外的參數(shù)傳遞。
當(dāng)然,如果確實(shí)對參數(shù)的傳遞,ebx、ecx、edx、esi、edi、ebp這幾個(gè)寄存器究竟是從左到右還是從右到左地存儲我們傳遞的參數(shù),實(shí)際上是arg1對應(yīng)ebx,arg2對應(yīng)ecx,以此類推。function(arg1, arg2, arg3, arg4, arg5, arg6);
- 由于Linux內(nèi)核中沒有調(diào)試器,理論上,如果真的想調(diào)試內(nèi)核的工作過程,需要用更加geek的方法。通過一些強(qiáng)大的第三方工具,如kdb、kgdb對內(nèi)核打補(bǔ)丁,將這些調(diào)試器附加到內(nèi)核上,就可以完成調(diào)試內(nèi)核的心愿。
調(diào)試是軟件開發(fā)過程中一個(gè)必不可少的環(huán)節(jié),在 Linux 內(nèi)核開發(fā)的過程中也不可避免地會面對如何調(diào)試內(nèi)核的問題。但是,Linux 系統(tǒng)的開發(fā)者出于保證內(nèi)核代碼正確性的考慮,不愿意在 Linux 內(nèi)核源代碼樹中加入一個(gè)調(diào)試器。他們認(rèn)為內(nèi)核中的調(diào)試器會誤導(dǎo)開發(fā)者,從而引入不良的修正[1]。所以對 Linux 內(nèi)核進(jìn)行調(diào)試一直是個(gè)令內(nèi)核程序員感到棘手的問題,調(diào)試工作的艱苦性是內(nèi)核級的開發(fā)區(qū)別于用戶級開發(fā)的一個(gè)顯著特點(diǎn)。
可以看到,我們在sys_getpid處設(shè)置了斷點(diǎn)。
c運(yùn)行,由于我們正常的啟動流程,系統(tǒng)并不會觸發(fā)斷點(diǎn)。
執(zhí)行我們想要的程序,因?yàn)闋可娴较到y(tǒng)調(diào)用,故運(yùn)行到斷點(diǎn)處停下。
- 可以看到,系統(tǒng)停在了SYSCALL_DEFINE0(getpid)處,此時(shí),我們不再用n、s進(jìn)行源碼的運(yùn)行,而是用ni、si運(yùn)行匯編代碼。
si一步一步運(yùn)行,可以發(fā)現(xiàn),運(yùn)行到了syscall_exit處:
syscall_exit:
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work
接下來,代碼的運(yùn)行過程,像是進(jìn)入了一個(gè)混沌世界。
通過跟蹤,可以發(fā)現(xiàn),大概系統(tǒng)執(zhí)行了INTERRUPT_RETURN之后便返回了。
- 有個(gè)奇怪的問題,發(fā)現(xiàn)我用C語言和用匯編語言寫的兩份系統(tǒng)調(diào)用的特性不太一致,路徑不一樣。
- C語言寫的話,只能第一次在系統(tǒng)中斷處停下,如果是匯編,則每次都能在中斷處停下。
- 這說明什么呢,C語言的庫函數(shù)getpid()實(shí)現(xiàn)的邏輯我們未知,需要再次發(fā)掘。
至于調(diào)度點(diǎn),暫時(shí)還未發(fā)現(xiàn)。