網(wǎng)易云課堂《Linux內(nèi)核分析》作業(yè)
實驗?zāi)康模?/h1>
使用庫函數(shù)API和C代碼中嵌入?yún)R編代碼兩種方式使用同一個系統(tǒng)調(diào)用倾贰,理解系統(tǒng)調(diào)用的工作機制谅辣。
實驗過程:
本文實驗使用亞馬遜云計算平臺(AWS)Ubuntu 14.04.2 LTS 64bit
本文實驗選擇24號和47號系統(tǒng)調(diào)用一铅,分別獲取當前用戶uid(用戶ID)和gid(組ID),即模擬Linux系統(tǒng)“id”命令本今。
編寫兩段代碼宰僧,分別使用庫函數(shù)API和C代碼中嵌入?yún)R編代碼,源碼如下:
uidgid.c(使用庫函數(shù)API方式):
程序中通過調(diào)用getuid()和getgid()函數(shù)來獲取當前執(zhí)行用戶uid和gid
參考:《Advanced Programming in the UNIX Environment》
uidgid_asm.c(使用C代碼中嵌入?yún)R編代碼方式):
內(nèi)嵌匯編代碼版本源碼中將原來兩行通過API函數(shù)獲取uid和gid的代碼注釋掉您市,用匯編代碼替換觉痛。
首先將ebx寄存器清零,表示無參數(shù)傳入茵休。
然后分別將0x18和0x2f(十進制24和47)賦值給eax寄存器薪棒,表示需要調(diào)用的系統(tǒng)調(diào)用號,24為getuid榕莺,47為getgid俐芯。
執(zhí)行int 0x80來執(zhí)行系統(tǒng)調(diào)用。
之后eax寄存器保存了返回值帽撑,將它分別賦值給輸出uid或gid變量泼各。
完成整個匯編代碼的系統(tǒng)調(diào)用。
分別編譯兩個源碼文件:
分別執(zhí)行系統(tǒng)id命令以及兩個編譯好的程序:
上面的截圖分別表示普通用戶ubuntu和管理員用戶root分別執(zhí)行系統(tǒng)自帶命令id亏拉,庫函數(shù)API方式uidgid扣蜻,內(nèi)嵌匯編方式uidgid_asm這三種方式運行得到的結(jié)果是一樣的。
實驗分析:
通過實驗執(zhí)行結(jié)果可知及塘,程序成功完成了系統(tǒng)調(diào)用獲取當前用戶uid和gid的操作莽使,通過內(nèi)嵌匯編代碼可以清晰的看出調(diào)用系統(tǒng)調(diào)用的工作過程。
首先將ebx寄存器清零笙僚,表示無參數(shù)傳入芳肌。
然后分別將0x18和0x2f(十進制24和47)賦值給eax寄存器,表示需要調(diào)用的系統(tǒng)調(diào)用號肋层,24為getuid亿笤,47為getgid。
執(zhí)行int 0x80來執(zhí)行系統(tǒng)調(diào)用栋猖。
之后eax寄存器保存了返回值净薛,將它分別賦值給輸出uid或gid變量。
完成整個匯編代碼的系統(tǒng)調(diào)用蒲拉。
在Linux系統(tǒng)中是通過激活0x80中斷來觸發(fā)系統(tǒng)調(diào)用的肃拜,需要調(diào)用的系統(tǒng)調(diào)用號實現(xiàn)賦值給eax存儲器痴腌,如果有傳入?yún)?shù)可賦值給ebx寄存器,如果多于1個則按順序賦值給ebx燃领、ecx士聪、edx、esi猛蔽、edi剥悟、ebp,如果超過6個則通過指針變量指向另一片堆棧區(qū)枢舶,如果無參數(shù)傳入則賦值為0懦胞。
實驗總結(jié):
雖然Intel X86 CPU有4種執(zhí)行級別0~3替久,但是在Linux系統(tǒng)中僅使用了0和3級凉泄,分別表示內(nèi)核態(tài)和用戶態(tài)。
一些涉及底層蚯根、硬件后众、核心的操作必須在內(nèi)核態(tài)下才允許執(zhí)行,為操作系統(tǒng)程序和驅(qū)動程序?qū)O砺梗胀ǔ绦騼H能執(zhí)行在用戶態(tài)下蒂誉。如果普通程序需要涉及內(nèi)核態(tài)的操作,就需要通過系統(tǒng)調(diào)用來實現(xiàn)距帅。這樣做的好處是屏蔽平臺相關(guān)操作降低了軟件開發(fā)難度右锨,增強了系統(tǒng)安全性,使程序具有更好的移植性(Linux系統(tǒng)及其他Unix系統(tǒng)遵循統(tǒng)一標準碌秸,系統(tǒng)調(diào)用基本一樣)绍移。
aapu原創(chuàng)作品轉(zhuǎn)載請注明出處《Linux內(nèi)核分析》MOOC課