2018-2019-1 20189218《Linux内核原理与分析》第五周作业
系統(tǒng)調(diào)用的三層機(jī)制
用戶態(tài)、內(nèi)核態(tài)和中斷
- 用戶態(tài)。較低的執(zhí)行級別,只能訪問一部分內(nèi)存,只能執(zhí)行一部分指令。
- 內(nèi)核態(tài)。高級執(zhí)行級別,可以訪問任意物理內(nèi)存,可以執(zhí)行特權(quán)指令。
- 中斷。系統(tǒng)從用戶態(tài)進(jìn)入內(nèi)核態(tài)的主要方式。有硬件中斷和軟中斷。系統(tǒng)調(diào)用就是通過軟中斷進(jìn)入內(nèi)核態(tài)。
上下文切換
用戶態(tài)切換到內(nèi)核態(tài)時,就要把用戶態(tài)寄存器上下文保存起來,同時要把內(nèi)核態(tài)寄存器的值放到當(dāng)前cpu中。int指令出發(fā)中斷機(jī)制會在堆棧上保存一些寄存器的值,會保存(SAVE_ALL)用戶態(tài)棧頂?shù)闹?/strong>,當(dāng)時的狀態(tài)字(flag),當(dāng)時的CS:EIP的值。同時會將內(nèi)核態(tài)的這些寄存器的值加載到cpu。其中內(nèi)核態(tài)CS:EIP指向中斷處理程序的入口,如果是系統(tǒng)調(diào)用則指向system_call,當(dāng)中斷結(jié)束后執(zhí)行restore_all和INTERRUPT_RETURN。
API和系統(tǒng)調(diào)用
API就是系統(tǒng)調(diào)用的庫函數(shù),是一個函數(shù)定義。系統(tǒng)調(diào)用是通過軟中斷向內(nèi)核發(fā)出了中斷請求,int指令的執(zhí)行就會觸發(fā)一個中斷請求,一個API可能只對應(yīng)一個系統(tǒng)調(diào)用,也可能由多個系統(tǒng)調(diào)用實現(xiàn)。
Linux中通過int $0x80來觸發(fā)系統(tǒng)調(diào)用的執(zhí)行,內(nèi)核給每個系統(tǒng)調(diào)用一個編號,即系統(tǒng)調(diào)用號來指明是哪個系統(tǒng)調(diào)用,通過EAX寄存器傳遞。
無參數(shù)系統(tǒng)調(diào)用
依次通過c語言和內(nèi)嵌匯編的c語言實現(xiàn)time()函數(shù)中封裝的系統(tǒng)調(diào)用。
time.c
課本上給出的time.c在編譯時遇到如下問題:
查看struct tm發(fā)現(xiàn)應(yīng)該是mday:
修改后代碼如下:
修改后順利運行:
內(nèi)嵌匯編的代碼運行順利:
自選系統(tǒng)調(diào)用access
其實沒什么大區(qū)別,C語言代碼及運行結(jié)果如圖:
內(nèi)嵌匯編的代碼及運行結(jié)果如圖,比c語言代碼有所簡化:
帶兩個參數(shù)的系統(tǒng)調(diào)用
同樣運行順利,代碼如下:
通用庫函數(shù)syscall
新增的沒有被封裝好的系統(tǒng)調(diào)用可以通過syscall(系統(tǒng)調(diào)用號,參數(shù)表)實現(xiàn),實際上比前兩種方式舒服很多。
于是我們需要知道系統(tǒng)調(diào)用對應(yīng)的系統(tǒng)調(diào)用號,在編譯器中通過查看syscall.h中引用的unistd.h文件可以查看系統(tǒng)定義的系統(tǒng)調(diào)用號表。
至于為什么unistd.h中的宏定義的變量名和我們使用的不一樣,是因為在bits/syscall.h中又進(jìn)行了一次宏定義:
這樣應(yīng)該更有益于程序的可讀性和不同版本的兼容性(兼容性是官方的解釋,但我現(xiàn)在對不同版本之間的兼容不報什么希望)。
感想
在查看系統(tǒng)調(diào)用號表時,實際上系統(tǒng)中有大量的unistd.h,包括i386、x86_64安裝過的mykernel和Linuxkernel以及許多不知道來源的。通常是在/usr/include/asm目錄下,但在我的電腦上甚至沒有asm這個目錄。還好編譯器中鏈接到的文件是在搜索目錄中的,所以能比較快的找到需要的頭文件。
之前在編程中要用到系統(tǒng)中的命令都是由system(command)實現(xiàn),現(xiàn)在想來這應(yīng)該是通過shell的封裝來調(diào)用的系統(tǒng)函數(shù),效率應(yīng)該比直接在程序中進(jìn)行系統(tǒng)調(diào)用低不少。
一個小問題
這章之后對Linux系統(tǒng)的層次似乎多了些理解。按照我的理解,內(nèi)核處于最底層,c語言中的系統(tǒng)調(diào)用和shell中的內(nèi)建命令都是通過調(diào)用內(nèi)核中的函數(shù)實現(xiàn),是對內(nèi)核中的函數(shù)的不同的封裝。C語言中syscall()是直接調(diào)用內(nèi)核中的函數(shù),而C語言中的system()函數(shù)則是通過調(diào)用shell間接的調(diào)用內(nèi)核中的函數(shù),所以命令可以和終端中的寫法保持一致,傳參也是直接傳字符串。希望這么理解是對的,在以后的實踐中去檢驗。
轉(zhuǎn)載于:https://www.cnblogs.com/thechosenone95/p/9932535.html
總結(jié)
以上是生活随笔為你收集整理的2018-2019-1 20189218《Linux内核原理与分析》第五周作业的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AVS 通信模块之HTTP2Transp
- 下一篇: zanePerfor 一款完整,高性能,