Linux內核分析第六次作業
阿新 • • 發佈:2018-11-18
fine 內核 分享 壓棧 ima () push 是否 oba
分析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),其中可能還會發生中斷上下文的切換和進程上下文的切換;
在當前進程的時候,有些信號可能需要處理。
內核可以抽象成是很多種不同的中斷處理過程的集合
Linux內核分析第六次作業