1. 程式人生 > >5_gdb跟蹤分析系統呼叫system_call的處理過程

5_gdb跟蹤分析系統呼叫system_call的處理過程

http://mooc.study.163.com/course/USTC-1000029000

==========================================================================

這周的實驗在上週實驗四的基礎上,進一步的操作:
1.將系統呼叫函式getpid命令加入menuos中
2.通過gdb跟蹤sys_getpid系統呼叫執行的完整過程

步驟:給MenuOS增加getpid和getpid-asm命令
0)更新menu程式碼到最新版
1)在main函式中增加MenuConfig
2)增加對應的getpid函式和getpid-asm函式
3)make rootfs


進入實驗樓環境後,敲入如下命令:

<span style="font-size:14px;">cd LinuxKernel
cd menu
vi test.c</span>

進入test.c源程式後新增如下程式碼:

<span style="font-size:14px;">//新增兩個函式,別忘了加標頭檔案#include <unistd.h>
int main() {
    pid_t tt;
    asm volatile (
            "movl $0x20, %%eax\n\t"
            "int $0x80\n\t"
            "movl %%eax, %0\n\t"
            :"=m"(tt)
            );
    printf("%u\n", tt);
    return 0;
}

int main() {
    pid_t tt;
    tt = getpid();
    printf("%u\n", tt);
    return 0;
}</span>
<span style="font-size:14px;">//然後在main函式中新增
MenuConfig("time","Show System Time",Time);
MenuConfig("time-asm","Show System Time(asm)",TimeAsm);</span>

程式碼新增完成後make rootfs重新編譯,此時系統會自動啟動。如下圖:


下面用gdb跟蹤sys_getpid執行的過程:
1.執行以下命令開啟核心的除錯功能 qemu -kernel linux-3.18.6/arch/x86/boot/bz/Image -initrd rootfs.img -s -S,此時系統處於停止狀態
2.再開啟一個命令列視窗輸入gdb,在gdb命令提示符下依次輸入file linux-3.18.6/vmlinux, target remote:1234命令連線核心並跟蹤除錯
3.設定斷點break sys_getpid, 接著continue開始執行,此時menuOS從stopped狀態開始執行。在menu程式的提示符下輸入who,程式執行到斷點時暫停,此時gdb視窗顯示程式斷在sys_getpid處
4.接著使用gdb單步執行命令。next:不進入函式體的單步執行;step:進入函式體的單步執行;finish:進入函式體後退回撥用函式


 

分析
中斷相關的初始化程式碼是通過linux-3.18.6/init/main.c檔案中的start_kernel函式裡的trap_init()初始化的。執行int $0x80指令後核心開始執行system_call入口處開始的程式碼,位於entry_32.S彙編檔案中。
下面分析system_call彙編程式碼:

<span style="font-size:14px;"># system call handler stub
ENTRY(system_call)
    RING0_INT_FRAME            		# can't unwind into user space anyway
    ASM_CLAC
    pushl_cfi %eax            		# save orig_eax
    SAVE_ALL                             
    GET_THREAD_INFO(%ebp)
   # system call tracing in operation / emulation
    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)
syscall_after_call:
    movl %eax,PT_EAX(%esp)        		# store the return value
syscall_exit:
    LOCKDEP_SYS_EXIT
    DISABLE_INTERRUPTS(CLBR_ANY)    	# make sure we don't miss an interrupt
   # setting need_resched or sigpending
   # between sampling and the iret
    TRACE_IRQS_OFF
    movl TI_flags(%ebp), %ecx
    testl $_TIF_ALLWORK_MASK, %ecx    	# current->work
    jne syscall_exit_work

restore_all:
    TRACE_IRQS_IRET
restore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
    movl PT_EFLAGS(%esp), %eax    		# mix EFLAGS, SS and CS
    # Warning: PT_OLDSS(%esp) contains the wrong/random values if we
    # are returning to the kernel.
    # See comments in process.c:copy_thread() for details.
    movb PT_OLDSS(%esp), %ah
    movb PT_CS(%esp), %al
    andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
    cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
    CFI_REMEMBER_STATE
    je ldt_ss            			# returning to user-space with LDT SS
#endif
restore_nocheck:
    RESTORE_REGS 4            		# skip orig_eax/error_co
de
irq_return:
    INTERRUPT_RETURN</span>

1.SAVE ALL                                // 儲存呼叫前暫存器相關的資訊

2.call *sys_call_table(,%eax,4)   // 執行系統呼叫對應的處理函式,eax存放系統呼叫號

                                                    // 通過linux-3.18.6/arch/x86/syscalls/syscall_32.tbl找到系統呼叫號對應處理函式

3.movl %eax,PT_EAX(%esp)     // 儲存系統呼叫處理函式返回值到exa

4. testl $_TIF_ALLWORK_MASK, %ecx    # current->work
    jne syscall_exit_work 
                                                   // 這兩句檢查呼叫退出前是否有其他工作要處理,如有則跳到syscall_exit_work處繼續處理,以下是syscall_exit_work相關程式碼:
syscall_exit_work:
    testl $_TIF_WORK_SYSCALL_EXIT, %ecx    // 測試是否退出前還有工作要處理,如有則跳到work_pending
    jz work_pending          
    TRACE_IRQS_ON
    ENABLE_INTERRUPTS(CLBR_ANY)    # could let syscall_trace_leave() call
                    # schedule() instead
    movl %esp, %eax
    call syscall_trace_leave
    jmp resume_userspace
END(syscall_exit_work)

5.下面是work_pending的相關程式碼,在註釋中解釋相關內容
work_pending:
    testb $_TIF_NEED_RESCHED, %cl       // 是否有要繼續排程的相關訊號
    jz work_notifysig      #跳轉到處理訊號相關的程式碼處
work_resched:
    call schedule                                         // 時間排程,程序排程的時機在這裡處理
    LOCKDEP_SYS_EXIT
    DISABLE_INTERRUPTS(CLBR_ANY)    # make sure we don't miss an interrupt
                    # setting need_resched or sigpending
                    # between sampling and the iret
    TRACE_IRQS_OFF
    movl TI_flags(%ebp), %ecx
    andl $_TIF_WORK_MASK, %ecx    # is there any work to be done other  // 是否有其他工作要處理
                                                          # than syscall tracing?
    jz restore_all                // 如果沒有則恢復中斷上下文,即恢復進入之前儲存的暫存器內容
    testb $_TIF_NEED_RESCHED, %cl
    jnz work_resched

work_notifysig:                # deal with pending signals and    // 處理相關訊號程式碼
                                      # notify-resume requests
#ifdef CONFIG_VM86
    testl $X86_EFLAGS_VM, PT_EFLAGS(%esp)
    movl %esp, %eax
    jne work_notifysig_v86        # returning to kernel-space or
                                              # vm86-space
1:
#else
    movl %esp, %eax
#endif
    TRACE_IRQS_ON
    ENABLE_INTERRUPTS(CLBR_NONE)
    movb PT_CS(%esp), %bl
    andb $SEGMENT_RPL_MASK, %bl
    cmpb $USER_RPL, %bl
    jb resume_kernel
    xorl %edx, %edx
    call do_notify_resume
    jmp resume_userspace

#ifdef CONFIG_VM86
    ALIGN
work_notifysig_v86:
    pushl_cfi %ecx               # save ti_flags for do_notify_resume
    call save_v86_state        # %eax contains pt_regs pointer
    popl_cfi %ecx
    movl %eax, %esp
    jmp 1b
#endif
END(work_pending)

6. restore_all:
       RESTORE_INT_REGS     // 中斷返回之前恢復相關暫存器的內容

7.     irq_return:
      INTERRUPT_RETURN     // 這兩行程式碼主要是返回到使用者態

總結
1.執行int 0x80指令後系統從使用者態進入核心態,跳到system_call()函式處執行相應服務程序。在此過程中核心先儲存中斷環境,然後執行系統呼叫函式。
2.system_call()函式通過系統呼叫號查詢系統呼叫表sys_cal_table來查詢具體系統呼叫服務程序。
3.執行完系統呼叫後,iret之前,核心會檢查是否有新的中斷產生、是否需要程序切換、是否學要處理其它程序傳送過來的訊號等。
4.核心是處理各種系統呼叫的中斷集合,通過中斷機制實現程序上下文的切換,通過系統呼叫管理整個計算機軟硬體資源。
5.如沒有新的中斷,restore儲存的中斷環境並返回使用者態完成一個系統呼叫過程。

 

相關推薦

5_gdb跟蹤分析系統呼叫system_call處理過程

http://mooc.study.163.com/course/USTC-1000029000 ========================================================================== 這周的實驗在上週實驗四的基

《Linux作業系統分析》之分析系統呼叫system_call處理過程

本篇文章通過將上篇文章中使用庫函式API和C程式碼中嵌入彙編程式碼兩種方式設計的系統呼叫新增到系統menu中,來說明在Linux系統中,系統呼叫的實現的時機以及具體執行,以及一般的中斷處理過程。 相關知識 首先關於這篇文章會介紹一些用到的知識。 一、將系統呼叫號與相應的服務

2019-舉例跟蹤分析Linux內核5.0系統調用處理過程

pan system int 軟中斷 color 制作根文件系統 ubun div nbsp 簡介 學號520 實驗環境基於ubuntu18.04 選擇系統調用號20 getpid()分析 實驗目的 學會使用gdb工具跟蹤linux內核函數調用

舉例跟蹤分析Linux內核5.0系統調用處理過程

服務 符號 撰寫 源代碼 details 技術 inux roo 調用 學號最後三位編號:094原創作品轉載請註明出處 + https://github.com/mengning/linuxkernel/ 0.實驗內容 編譯內核5.0 qemu -kernel l

跟蹤分析Linux內核5.0系統調用處理過程

bubuko 內存空間 轉換 ase 運行 ubuntu fig 1.0 bss 學號尾號:155 基於ubuntu kylin 18.10虛擬機 原創作品轉載請註明出處https://github.com/mengning/linuxkernel/ 實驗準備 下載和編譯

大型企業級雲產品-數據統計分析系統(離線處理-流處理-批處理

大數據大型企業級雲產品-數據統計分析系統(離線處理-流處理-批處理)課程觀看地址:http://www.xuetuwuyou.com/course/249課程出自學途無憂網:http://www.xuetuwuyou.com講師:友凡 課程介紹本套教程為真實的大數據實戰案例,適合有大數據基礎的學員學習,熟練掌

wxWidgets源碼分析(4) - 消息處理過程

處理過程 HERE toe 處理流程 als upm 接收 entry false 目錄 消息處理過程 消息如何到達wxWidgets Win32消息與wxWidgets消息的轉換 菜單消息處理 消息處理鏈(基於wxEvtHandler) 消息處理鏈(基於wxWindow

Linux核心原始碼情景分析-系統呼叫mknod

    普通檔案可以用open或者create建立,FIFO檔案可以用pipe建立,mknod主要用於裝置檔案的建立。    在核心中,mknod是由sys_mknod實現的,程式碼如下:asmlinkage long sys_mknod(const char * filen

windows核心情景分析--系統呼叫

Windows的地址空間分使用者模式與核心模式,低2GB的部分叫使用者模式,高2G的部分叫核心模式,位於使用者空間的程式碼不能訪問核心空間,位於核心空間的程式碼卻可以訪問使用者空間 一個執行緒的執行狀態分核心態與使用者態,當指令位於使用者空間時,就表示當前處於核心態,當指令位於核心空間時,就處於核心態.

Windows核心情景分析-系統呼叫2

x86後來加入的快速系統呼叫硬體支援,windows則也跟著做了改動,此時如果cpu支援sysenter,則會採用快速系統呼叫的系統呼叫形式。  快速系統呼叫 sysenter 形式的系統呼叫例項 此時工具生成的NtReadFile為: 此時與int 0

Linux系統呼叫的執行過程

開發十年,就只剩下這套架構體系了! >>>   

Linux系統呼叫過程分析

Linux系統呼叫過程分析 參考: 《Linux核心設計與實現》 0 摘要 linux的系統呼叫過程:層次例如以下:使用者程式------>C庫(即API):INT 0x80 ----->system_call------->系

Linux--Sys_Read系統呼叫過程分析

注: 本片文章以Read函式的呼叫為例來講述一下系統對塊驅動層的一些處理, 哈哈。如果有不正確或者不完善的地方,歡迎前來拍磚留言或者發郵件到[email protected]進行討論,先行謝過。 一.Read函式經由的層次模型 首先來了解一下Read函式經由的

窺探 kernel,just for fun --- 系統呼叫過程分析

郵箱:[email protected] 過程分析: 1、系統呼叫需要一個使用者空間到核心空間的轉換,不同的平臺有不同的指令來完成這樣的轉換,這個指令也叫做作業系統陷入(operating systemtrap)指令。在linux中對於x86

使用gdb跟蹤分析一個系統呼叫核心函式

“郭孟琦 + 原創作品轉載請註明出處 + 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 ” 繼續上週的內容,首先利用gdb跟蹤系統呼叫system_call的處理過程。 這裡我繼續使用上

bat批處理指令碼呼叫oracle儲存過程系統定時呼叫指令碼

編寫一個bat批處理指令碼呼叫oracle儲存過程,並設定系統定時完成該指令碼任務,有以下幾個步驟: 1. 先編寫一個call.sql檔案: set timing on; DECLARE o_UserID varchar2(20); BEGIN Packag

系統呼叫執行過程分析

#####################################作者:張卓原創作品轉載請註明出處:《Linux作業系統分析》MOOC課程 http://www.xuetangx.com/courses/course-v1:ustcX+USTC001+_/about

系統呼叫入口函式原始碼分析system_call——X86_64

在實驗中用到這一塊,就去看原始碼分析整理了一下,全部為個人理解。有錯誤的地方,希望和大牛交流。 首先解釋一下,我實驗的目的是獲得系統呼叫入口函式system_call的起始地址和函式大小。 在linux-3.10.1, x86 64位的系統下,系統呼叫的入口地址儲存在MSR暫存器中,通過rdmsrl(MSR

Linux核心分析(五)系統呼叫過程解析

禹曉博+ 原創作品轉載請註明出處 + 歡迎加入《Linux核心分析》MOOC網易雲課堂學習 一、系統呼叫流程分析         系統呼叫系統呼叫就是使用者空間應用程式和核心提供的服務之間的一個介面。由於服務是在核心中提供的,因此無法執行直接呼叫;相反,我們必須使用一個程序

Linux核心:基於int指令的經典系統呼叫過程分析

眾所周知,程式碼執行可以存在多種不同的特權級別,而針對Linux系統,即為:使用者模式(user mode)和核心模式(kernel mode)。在使用者模式下,CPU的功能空間受到極大的限制,是沒有權利訪問多少系統資源的,諸多關鍵資源的使用無法直接調配,如:硬