1. 程式人生 > >Linux內核分析第六次作業

Linux內核分析第六次作業

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內核分析第六次作業