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






