system_call的處理過程


一. 跟蹤time系統調用

使用gdb調試跟蹤系統調用內核函數sys_time

過程如下:

  • 對sys_time設置斷點之后,在menuOS中執行time命令,發現系統停在systime處,輸入S單步執行,知道函數return i;
  • sys_time返回之后進入匯編代碼處理,gdb無法繼續跟蹤。
  • 如果在syscall設置斷點(entry32.S),然后輸入c之后,發現是不會在sys_call處停下來的(因為這里是一處系統調用函數而不是正常函數)。

二. 系統調用在內核代碼中的處理過程

1.系統調用在內核代碼中的工作機制和初始化

整個系統調用過程中,時間很重要。
以system_call為例,int 0x80指令與sys_call是通過中斷向量聯系起來的,而API和對應的sys是通過系統調用號聯系起來的

用戶態時,系統調用xyz()使用int 0x80,它對應調用system_call

右邊的處理過程(匯編代碼)非常重要,通過系統調用號匹配起來

2.系統調用機制的初始化

trap_init函數里面有一個set_system_trap_gate函數,其中涉及到了系統調用的中斷向量SYSCALL_VECTOR和匯編代碼入口system_call,一旦執行int 0x80,CPU直接跳轉到system_call來執行。

3.簡化后便於理解的system_call偽代碼

  1. systemcall的位置就在ENTRY(systemcall)處,其他中斷的處理過程與此類似。

  • 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,結束。



偽代碼簡化了下

SAVE_ALL與sys_call_table系統調用分派表,對應的處理函數分別是:

 

sys_call_table(,%eax,4)

 

JMP(EAX*4 + system_xxx)

1.在系統調用返回之前,可能發生進程調度,進程調度里就會出現進程上下文的切換 2.進程間通信可能有信號需要處理

 

4.簡單瀏覽system_call到iret之間的主要代碼

  1. SAVE_ALL:保存現場
  2. syscall_call:調用了系統調用處理函數
  3. restore all:恢復現場(因為系統調用處理函數也算是一種特殊的“中斷”)
  4. syscallexitwork:如3.中所述
  5. INTERRUPT RETURN:也就是iret,系統調用到此結束

三.system_call到iret過程流程圖

等會看下視頻補張圖

 

三、總結

(一)從系統調用處理過程到一般的中斷處理過程

1. 保存現場

  • 在系統調用時,用SAVE_ALL來保存系統調用時的上下文。
  • 中斷處理的第一步也是要保存中斷程序現場。
  • 中斷處理完之后,可以返回到原來被中斷的地方,在原有的運行環境下繼續正確的執行下去。

2. 確定中斷信息

  • 在系統調用中,需要將系統調用號通過eax傳入,通過sys_call_table查詢到調用的系統調用,然后跳轉到相應的程序進行處理。
  • 中斷處理時系統也需要有一個中斷號,通過檢索中斷向量表,了解中斷的類型和設備。

3. 處理中斷

  • 跳轉到相應的中斷處理程序后,對中斷進行處理。

4. 返回

  • 系統調用時最后要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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM