標籤:
一.使用gdb跟蹤分析一個系統調用核心功能
1.在test.c檔案中添加time函數與採用c語言內嵌彙編的time函數.具體實現請看.
2.然後在main函數中添加MenuConfig函數,進行註冊。這樣當Menuos運行起來時,介面就會多出time與time-asm選項。
3.通過make rootfs命令運行
採用gdb調試的過程
- qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
- gdb
- file linux-3.18.6/vmlinux
- target remote:1234
- b start_kernel
- b sys_time
gdb單步調試命令n,繼續運行c,跳入函數核心s.
二.分析system_call代碼的執行過程
當使用者調用一個系統調用時,系統會自動通過int $0x80進入核心,同時通過中斷向量進入system_call函數.然後開始執行system_call過程。
490ENTRY(system_call)491 RING0_INT_FRAME # can‘t unwind into user space anyway492 ASM_CLAC493 pushl_cfi %eax # save orig_eax494 SAVE_ALL #儲存寄存器上下文環境495 GET_THREAD_INFO(%ebp) 496 # system call tracing in operation / emulation497 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)498 jnz syscall_trace_entry499 cmpl $(NR_syscalls), %eax500 jae syscall_badsys501syscall_call:502 call *sys_call_table(,%eax,4) #通過eax寄存器儲存的具體系統調用號來去system_call表中去執行具體的系統調用503syscall_after_call:504 movl %eax,PT_EAX(%esp) #系統調用執行完之後用eax儲存傳回值505syscall_exit:506 LOCKDEP_SYS_EXIT507 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don‘t miss an interrupt508 # setting need_resched or sigpending509 # between sampling and the iret510 TRACE_IRQS_OFF511 movl TI_flags(%ebp), %ecx512 testl $_TIF_ALLWORK_MASK, %ecx # current->work,判斷當前是否需要繼續執行syscall_exit_word過程513 jne syscall_exit_work #若需要,則進入syscall_exit_work過程514515restore_all:516 TRACE_IRQS_IRET #恢複上下文環境
這段代碼的總體流程就是:
- 儲存當前進程環境(SAVE_ALL)
- 執行具體的系統調用,並儲存傳回值
- 判斷當前是否還需要執行其他的任務(即syscall_exit_work).
- 恢複上下文環境。
接下來具體看看syscall_exit_work執行了哪些具體任務
656syscall_exit_work:657 testl $_TIF_WORK_SYSCALL_EXIT, %ecx658 jz work_pending #進入work_pending659 TRACE_IRQS_ON660 ENABLE_INTERRUPTS(CLBR_ANY) # could let syscall_trace_leave() call661 # schedule() instead662 movl %esp, %eax663 call syscall_trace_leave664 jmp resume_userspace665END(syscall_exit_work)
work_pending的主要工作是判斷當前進程是否有訊號或者進程通訊的任務來處理。
593work_pending:594 testb $_TIF_NEED_RESCHED, %cl595 jz work_notifysig #如果有訊號處理,則進入work_notifysig過程596work_resched: 597 call schedule #是否需要進行進程調度,如果有進程調度的任務,則進入598 LOCKDEP_SYS_EXIT599 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don‘t miss an interrupt600 # setting need_resched or sigpending601 # between sampling and the iret602 TRACE_IRQS_OFF603 movl TI_flags(%ebp), %ecx604 andl $_TIF_WORK_MASK, %ecx # is there any work to be done other605 # than syscall tracing?606 jz restore_all #返回進行上下文607 testb $_TIF_NEED_RESCHED, %cl 608 jnz work_resched609
因此在進程執行完某個系統調用的過程後,在傳回值之前,會檢查是否進程有訊號需要處理和是否有進程調度的任務需要執行。
三.實驗總結
更加進一步地深入學習了在使用者調用一個系統調用時,核心底層的執行過程。
《Linux核心分析》 week5作業-system call中斷處理過程