1. 程式人生 > >2018-2019-1 20189203《linux核心原理與分析》第六週作業

2018-2019-1 20189203《linux核心原理與分析》第六週作業

第一部分

  • 給Menu OS增加命令
    輸入命令
    rm -rf menu git clone http://github.com/mengning/menu.git make rootfs
  • 檢視增加的time 和time_asm命令

    第二部分 實驗(使用gdb跟蹤呼叫核心函式)

    1.操作

    我選用的是上週使用的rename,首先編輯menu中的test.c檔案,給MenuOS增加rename和rename_asm命令,如圖

    執行可以看到MenuOS中新增兩條命令:

    使用gdb跟蹤sys_rename,在sys_rename處設定斷點,在MenuOS中執行rename命令,停在SyS_rename處,然後單步執行。

    2.系統呼叫處理過程分析。

    系統呼叫機制的初始化是在 start_kernel 中的 trap_init()裡進行的,如下程式,SYSCALL_VECTOR系統呼叫的中斷向量,&system_call是 system_call的入口,一旦執行int 0x80,CPU就會立即跳轉到此處。
    #ifdef CONFIG_X86_32 set_system_trap_gate(SYSCALL_VECTOR, &system_call); set_bit(SYSCALL_VECTOR, used_vectors); #endif
    將system_call程式碼簡化並加以分析:
     RING0_INT_FRAME    
     ASM_CLAC        
     pushl_cfi %eax            //儲存系統呼叫號;
     SAVE_ALL                  //將用到的所有CPU暫存器儲存到棧中
     GET_THREAD_INFO(%ebp)     //ebp用於存放當前程序thread_info結構的地址
     testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
     jnz syscall_trace_entry
     cmpl $(nr_syscalls), %eax  //檢查系統呼叫號
     jae syscall_badsys         //不合法,跳入到異常處理
 syscall_call:
     call *sys_call_table(,%eax,4) //對照系統呼叫號在系統呼叫表中尋找相應服務例程
     movl %eax,PT_EAX(%esp)        //儲存返回值到棧中
 syscall_exit:  
     testl $_TIF_ALLWORK_MASK, %ecx   //檢查是否需要處理訊號
     jne syscall_exit_work        //需要,進入 syscall_exit_work,這裡是最常見的系統排程時機
 restore_all: 
     TRACE_IRQS_IRET              //恢復現場 
 irq_return:
     INTERRUPT_RETURN             //iret

從entry(system_call)開始看這段程式碼,根據系統呼叫號來查sys_call_table表中的位置,呼叫系統呼叫對應的系統函式,在syscall_exit裡面判斷當前的任務是否需要處理syscall_exit_work,進入syscall_exit_work,這是最常見的程序排程時機點。
System_call流程圖如下圖所示:

如圖,流程圖中涉及syscall_exit_work內部處理的一些關鍵點,大致的過程是syscall_exit_work需要跳轉到work_pending,裡面有work_notifysig處理訊號。還有work_resched是需要重新排程的,這裡是程序排程的時機點call schedule,排程完後之後就會跳轉到restore_all,恢復現場返回系統呼叫到使用者態。