1. 程式人生 > >20189220 餘超《Linux核心原理與分析》第六週作業

20189220 餘超《Linux核心原理與分析》第六週作業

系統呼叫的三層機制

實驗過程

1.克隆MenuOS

rm menu -rf //強制刪除當前menu
git clone http://git.shiyanlou.com/mengning/menu.git //重新克隆新版本的menu
cd menu
ls

2.開啟test.c並在裡面新增上次實驗所用的getpid的c函式和彙編程式碼

3.在main函式中加入MenuConfig

4.make rootfs

5.使用hellp命令可以看到qemu中增加了我們先前新增的命令:

6.執行新增加的命令getpid getpid_asm可得:

7.gdb跟蹤分析一個系統呼叫核心函式

8.在start_kernel處設定斷點,繼續執行,在qemu視窗的結果:

9.檢視我所選用的系統呼叫的函式:

10.設定斷點在sys_getpid處,發現執行命令getpid時並沒有停下,在執行getpid_asm時停下了:

11.直接結束若干次單步執行,然後繼續往下單步執行,發現出現了程序排程函式,返回了程序排程中的一個當前程序任務的值。

12.設定斷點於system_call處。發現可停,而繼續執行時,剛才停下的getuid_asm也返回了值。

實驗分析

  1. 系統呼叫在核心程式碼中的工作機制和初始化
  • main.c中start_kernel函式:trap_init()
  • set_system_trap_gate(SYSCALL_VECTOR,&system_call)
  • SYSCALL_VECTOR:系統呼叫的中斷向量
  • &system_call:彙編程式碼入口——執行int 0x80,系統直接跳轉到system_call。

2.系統呼叫——一個特殊的中斷

  • SAVE_ALL:儲存現場
  • call *sys_call_table(,%eax,4)呼叫了系統排程處理函式,eax存的是系統呼叫號,是實際的系統排程程式。
  • sys_call_table:系統呼叫分派表,syscall_after_all:儲存返回值
  • 若有sys_exit_work,則進入sys_exit_work:會有一個程序排程時機。work_pending -> work_notifysig,用來處理訊號 可能call schedule:程序排程程式碼可能跳轉到restore_all,恢復現場。
  • 若無sys_exit_work,就執行restore_all恢復,返回使用者態INTERRUPT_RETURN <=> iret,結束。
在系統呼叫返回之前,可能發生程序排程,程序排程裡就會出現程序上下文的切換。
程序間通訊可能有訊號需要處理。
可以將核心視為一系列中斷指令的集合。

3.system_call的流程示意圖

遇到的問題

在進行gdb除錯的時候,我匯入檔案的時候出現了下面的問題

原因:是因為我進入到了menu裡面去了,應該退出來回到LinuxKernel的目錄下面來執行除錯。

回到上面的目錄下載進行除錯就可以匯入檔案了

本章總結

  • 通過本章的學習和實驗,我首先明白了系統呼叫是一種特殊的中斷,初步理解了系統呼叫的過程。
  • 在系統呼叫時,我們需要SAVE_ALL,用於儲存系統呼叫時的上下文。同樣,中斷處理的第一步應該也要儲存中斷程式現場。目的:在中斷處理完之後,可以返回到原來被中斷的地方,在原有的執行環境下繼續正確的執行下去。
  • 在系統呼叫時,我們需要將系統呼叫號通過eax傳入,通過sys_call_table查詢到呼叫的系統呼叫,然後跳轉到相應的程式進行處理。同樣,中斷處理時系統也需要有一箇中斷號,通過檢索中斷向量表,瞭解中斷的型別和裝置。
  • 系統呼叫時最後要restore_all恢復系統呼叫時的現場,並用iret返回使用者態。同樣,執行完中斷處理程式,核心也要執行特定指令序列,恢復中斷時現場,並使得程序回到使用者態。

在實驗部分我學到了:給menuOS增加命令的方法:
強制刪除menu (rm menu -rf)
更新menu程式碼至最新版本(git clone https://github.com/mengning/menu.git
在test.c中main函式中增加MenuConfig,以及增加上週自己選擇Getegid,GetegidAsm的程式碼
Make roofts自動編譯,生成,和啟動根檔案系統

使用gdb跟蹤除錯核心的方法:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
gdb
(gdb)file linux-3.18.6/vmlinux # 在gdb介面中targe remote之前載入符號表
(gdb)target remote:1234 # 建立gdb和gdbserver之間的連線,按c 讓qemu上的Linux繼續執行
(gdb)break start_kernel # 斷點的設定,注意尋找對應的系統呼叫函式名字,例如time命令對應sys_time