Linux核心分析第六次作業
阿新 • • 發佈:2018-11-19
分析system_call中斷處理過程
一、先在實驗樓的虛擬機器中MenuOs增加utsname和utsname-asm指令。
具體實現如下:
1、克隆最新新版本的menu,之後進入menu
2、進入test.c,完成之後make rootfs,使系統自動編譯自動執行
3.設定分割點,用gdb追蹤
4.設定斷點
二、然後開始使用gdb追蹤系統呼叫核心函式sys_time
1、設定斷點sys_time
2.繼續執行,系統會啟動到menuos,執行time命令(可發現此命令執行到一半卡住了),可以看到出現了一個斷點
3.繼續單步執行,直到出現return i
4.設定斷點(system_call),繼續執行可發現time有返回
三、系統呼叫分析
系統呼叫時使用者態進入核心態的唯一入口,常用的系統呼叫有:
控制硬體:如read/write呼叫;
設定系統狀態或讀取核心資料——getpid()、getpriority()、setpriority()、sethostname();
程序管理:fork()、clone()、execve()、exit()等。
- sys_call程式碼分析
push1 %eax /*將系統呼叫號壓棧*/ SAVE_ALL cmp1$(NR_syscalls),%eax /*檢查系統呼叫號*/ jb nobadsys mov1 $(-ENOSYS), 24(%esp) /*堆疊中的eax設定為-ENOSYS,作為返回值*/ jmp ret_from_sys_call nobadsys: call *sys_call_table(, %eax, 4) #呼叫系統呼叫表中呼叫號為eax的系統呼叫例程。 mov1 %eax,EAX(%esp) #將返回值存入堆疊中 jmp ret_from_sys_call
分析:
首先將系統呼叫號(eax)和可以用到的所有CPU暫存器儲存到相應的堆疊中(由SAVE_ALL完成); 對使用者態程序傳遞過來的系統呼叫號進行有效檢查(eax是系統呼叫號,它應該小於NR_syscalls),如果是合法的系統呼叫,再進一步檢測該系統呼叫是否正被跟蹤。根據eax中的 系統呼叫號呼叫相應的服務例程。 服務例程結束後,從eax暫存器獲得它的返回值,並把這個返回值存放在堆疊中,讓其位於使用者態eax暫存器曾存放的位置。然後跳轉到ret_from_sys_call(),終止系統呼叫程式的 執行。
- save_all程式碼分析
#define save_all
cld;
push1 %es;
push1 %ds;
push1 %eax;
push1 %ebp;
push1 %edi;
push1 %esi;
push1 %edx;
push1 %ecx;
push1 %ebx;
mov1 $(__KERNEL_DS),%edx;
mov1 %edx, %ds;
mov1 %edx,%es;
分析:
SAVE_ALL將暫存器的引數壓入到核心棧中(這樣核心才能使用使用者傳入的引數)。因為子啊不同特權級之間控制轉換時,INT指令不同於CALL指令,它不會將外層堆疊的引數
自動拷貝到內層堆疊中。所以在呼叫系統呼叫時,必須把引數指定到各個暫存器中。
四、從system_call開始到iret結束之間的整個過程,可以用流程圖表示如下:
五、總結
在系統呼叫返回之前,可能會發生程序排程(call_schedule),其中可能還會發生中斷上下文的切換和程序上下文的切換;
在當前程序的時候,有些訊號可能需要處理。
核心可以抽象成是很多種不同的中斷處理過程的集合