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

Linux核心分析第六次作業

分析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),其中可能還會發生中斷上下文的切換和程序上下文的切換;

  • 在當前程序的時候,有些訊號可能需要處理。

  • 核心可以抽象成是很多種不同的中斷處理過程的集合