課本:第五章 系統調用的三層機制(下)
- 中斷向量0x80和system_call中斷服務程序入口的關系
0x80對應著system_call中斷服務程序入口,在start_kernel函數中調用了trap_init函數,trap_init函數中調用了set_system_trap_gate函數,其中有系統調用的中斷向量0x80和system_call中斷服務程序入口的函數指針,system_call被聲明為一個函數,通過set_system_trap_gate函數綁定了中斷向量0x80和system_call中斷服務程序入口之后,一旦執行int 0x80,CPU就直接跳轉到system_call這個位置執行。 - 系統調用用戶態接口和系統調用的內核處理函數是通過系統調用號匹配起來的
system_call中斷服務程序執行流程
從entry(system_call)開始執行,根據系統調用號來查sys_call_table表中的位置,調用系統調用對應的處理函數,在syscall_exit里面判斷當前任務是否需要處理syscall_exit_work,進入syscall_exit_work,這是最常見的進程調度時機點。
其中sys_call_table(,%eax,4)可以理解為,分派表中每個表項占4個字節,所以先把系統調用號(eax)乘以4,再加上sys_call_table分派表的起始地址,得到系統調用號對應的系統調用內核處理函數的指針。
system_call的執行流程圖如下圖所示:
其中,cmpl部分是檢查系統調用號(應小于nr_syscalls),不合法即跳入syscall_badsys異常處理,movl部分是保存返回值到棧中,syscall_exit檢查是否有任務需要處理,有則進入syscall_exit_work,無則恢復現場。實驗:分析system_call中斷處理過程
上周我進行實驗選擇的系統調用是38號rename,首先修改menu目錄下的test.c文件,添加Rename函數,并在main里menuconfig方法里調用,如下圖所示:
在進行make rootfs后,在qemu中的執行效果如下:
后打開gdb,在gdb中調試,在start_kernel和rename的系統調用入口sys_rename兩個地方設置斷點,執行效果如下圖所示:
在menuOS中執行rename指令后,斷點停在sys_rename系統調用入口處,如下圖所示:
對system_call的流程理解見上部分流程圖所示。
總結
本周實驗是了解系統調用在內核代碼中的處理過程,實驗實踐起來會比較容易,但真正了解其在內核代碼中的處理過程是十分困難的,在gdb環境下有些特殊的匯編代碼還無法跟蹤調試。使用 ALD(Assembly Language Debugger)這個匯編代碼調試器可以完成匯編代碼的調試,這會在以后進行實現。總統來說,進行本實驗之后對system_call的關鍵流程有了清晰的了解,具體的細節指令還有待研究。
本周的實驗遇到一個路徑問題。在LinuxKernel/menu目錄下直接執行init可執行文件,在menuOS下執行rename指令,發現指令返回提示成功,并成功更改文件名,如下圖所示:
后把文件名更改回原文件名,在qemu環境下啟動內核和menuOS,執行rename指令,指令返回error,并未成功更改文件名,如下圖所示:
翻看rename函數源代碼,判斷應該是文件的路徑問題,源碼中使用的是相對路徑,更改文件路徑為絕對路徑依然不能成功更改文件名。就非常疑惑,qemu環境下運行menuOS默認的相對路徑到底在什么位置?
與同學討論,大多也遇到了這個問題。本來想使用mkdir系統調用指令來生成文件,后在shell中使用find指令查找此文件夾,但是遇到了訪問路徑權限不足的問題,升級到root權限也無濟于事。。。根據多個系統調用指令實驗初步猜想,qemu環境沒有默認的路徑,其直接從內存中讀寫文件。這只是猜想,還望了解此問題的同學、老師看到此博可以給予指導解答。