2018-2019-1 20189203《linux核心原理與分析》第六週作業
阿新 • • 發佈:2018-11-19
第一部分
- 給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,恢復現場返回系統呼叫到使用者態。