1. 寫在前面
?系統(tǒng)調(diào)用是操作系統(tǒng)提供給用戶程序調(diào)用的一組“特殊”接口。通過(guò)這組“特殊”接口,用戶程序可以獲得操作系統(tǒng)內(nèi)核提供的服務(wù),如文件系統(tǒng)相關(guān)系統(tǒng)調(diào)用提供的打開(kāi)文件、關(guān)閉文件或讀寫文件服務(wù),時(shí)鐘相關(guān)的系統(tǒng)調(diào)用提供的獲取系統(tǒng)時(shí)間、設(shè)置系統(tǒng)時(shí)間服務(wù)等。
?從邏輯上來(lái)說(shuō),系統(tǒng)調(diào)用可被看成是一個(gè)內(nèi)核與用戶空間程序交互的接口——好比一個(gè)中間人,把用戶進(jìn)程的請(qǐng)求傳達(dá)給內(nèi)核,待內(nèi)核把請(qǐng)求處理完畢后再將處理結(jié)果送回給用戶進(jìn)程。
一個(gè)系統(tǒng)調(diào)用的典型調(diào)用過(guò)程如下圖所示.

系統(tǒng)調(diào)用的作用:
?系統(tǒng)服務(wù)之所以需要通過(guò)系統(tǒng)調(diào)用提供給用戶空間,其根本原因是為了對(duì)系統(tǒng)進(jìn)行“保護(hù)”。我們知道操作系統(tǒng)的運(yùn)行空間分為內(nèi)核空間與用戶空間,它們各自運(yùn)行在不同的級(jí)別中,邏輯上相互隔離,故用戶進(jìn)程在通常情況下不允許訪問(wèn)內(nèi)核數(shù)據(jù)、不允許使用內(nèi)核函數(shù),它們只能在用戶空間操作用戶數(shù)據(jù),調(diào)用用戶空間的函數(shù)。但是很多情況下,用戶進(jìn)程需要獲得系統(tǒng)服務(wù)(調(diào)用系統(tǒng)程序),這時(shí)就必須利用系統(tǒng)提供給用戶的“特殊”接口——系統(tǒng)調(diào)用,其特殊性在于規(guī)定了用戶進(jìn)程進(jìn)入內(nèi)核的具體位置,即用戶訪問(wèn)內(nèi)核的路徑是事先規(guī)定好的,只能從規(guī)定位置進(jìn)入內(nèi)核,而不準(zhǔn)許肆意跳入內(nèi)核。有了上述陷入內(nèi)核的統(tǒng)一訪問(wèn)路徑限制,才能有效保證系統(tǒng)內(nèi)核的安全。我們可以形象地描述上述機(jī)制:作為一個(gè)游客,你可以買票要求進(jìn)入野生動(dòng)物園,但你必須老老實(shí)實(shí)的坐在觀光車上,按照規(guī)定的路線觀光游覽。當(dāng)然,不準(zhǔn)下車,因?yàn)槟菢犹kU(xiǎn),不是讓你丟掉小命,就是讓你嚇壞了野生動(dòng)物。
?在前述文章“Linux-3.10.1內(nèi)核的編譯和安裝”(詳見(jiàn)http://www.lingyuecloud.com/Index/details/id/58.html)中,我們知道利用Linux內(nèi)核的開(kāi)源特性,可以對(duì)Linux系統(tǒng)進(jìn)行定制化開(kāi)發(fā)、編譯和安裝。例如,通過(guò)修改Linux內(nèi)核源碼,我們定制化開(kāi)發(fā)了一個(gè)新功能,那么如何在應(yīng)用程序中使用這個(gè)新功能呢?為此,我們還需要為“應(yīng)用程序”與“內(nèi)核中新增的新功能”建立橋梁——即一個(gè)能夠連接兩者的系統(tǒng)調(diào)用。
?假設(shè)我們已經(jīng)獲得了Linux-3.10.1的源碼包linux-3.10.1.tar.bz2,解壓該源碼包后得到linux-3.10.1文件夾,并切換到該文件夾下(如何獲取包linux-3.10.1.tar.bz2?如何解壓?請(qǐng)?jiān)斠?jiàn)http://www.lingyuecloud.com/Index/details/id/58.html——“Linux-3.10.1內(nèi)核的編譯和安裝”)。接下來(lái),靈躍桌面云將以Linux-3.10.1內(nèi)核為例,詳細(xì)描述為內(nèi)核添加一個(gè)新的系統(tǒng)調(diào)用的過(guò)程,下述所有操作都在linux-3.10.1目錄下進(jìn)行。
2. 環(huán)境說(shuō)明

注:在下述描述中,涉及在服務(wù)器Ubuntu 12.04操作系統(tǒng)環(huán)境上的所有操作,均以root身份登錄并執(zhí)行。
3. 為L(zhǎng)inux-3.10.1內(nèi)核添加一個(gè)系統(tǒng)調(diào)用
3.1 系統(tǒng)調(diào)用號(hào)
?Linux系統(tǒng)調(diào)用號(hào)的作用是在系統(tǒng)調(diào)用過(guò)程中,將其數(shù)值作為下標(biāo)的在系統(tǒng)調(diào)用表中進(jìn)行索引,從而得到處理該系統(tǒng)調(diào)用的函數(shù)的地址。
?每個(gè)系統(tǒng)調(diào)用都有一個(gè)唯一的系統(tǒng)調(diào)用號(hào),應(yīng)用程序可以通過(guò)系統(tǒng)調(diào)用號(hào)調(diào)用指定的系統(tǒng)調(diào)用。
3.2 系統(tǒng)調(diào)用表
?與Windows系統(tǒng)中的SSDT(System Services Descriptor Table)的作用一樣,Linux系統(tǒng)調(diào)用表保留著處理各個(gè)系統(tǒng)調(diào)用的函數(shù)的入口地址;其實(shí)際上是一個(gè)二維的指針數(shù)組[X][Y],X代表系統(tǒng)調(diào)用號(hào),Y代表系統(tǒng)調(diào)用函數(shù)的入口地址。
3.3 添加系統(tǒng)調(diào)用lingyuecloudsyscall
- 添加自定義的系統(tǒng)調(diào)用源代碼
在“l(fā)inux-3.10.1/kernel”目錄下的sys.c文件中添加自定義的系統(tǒng)調(diào)用lingyuecloudsyscall的實(shí)現(xiàn)函數(shù)。
打開(kāi)sys.c文件,添加以下示例代碼:
#vim kernel/sys.c

|
- 修改系統(tǒng)調(diào)用表
系統(tǒng)調(diào)用表文件在“l(fā)inux-3.10.1/arch/x86/syscalls”目錄下的syscall_64.tbl文件中。
打開(kāi)syscall_64.tbl,添加新的系統(tǒng)調(diào)用指針,如下所示:
#vim arch/x86/syscalls/syscall_64.tbl

如下圖所示:

其中,314為lingyuecloudsyscall的系統(tǒng)調(diào)用號(hào),應(yīng)用程序可通過(guò)此調(diào)用號(hào)調(diào)用lingyuecloudsyscall系統(tǒng)調(diào)用,也可以使用其它的系統(tǒng)調(diào)用號(hào),但注意不能與已有的系統(tǒng)調(diào)用號(hào)重復(fù)。64表示適配于64位系統(tǒng)內(nèi)核環(huán)境,相關(guān)描述詳情可查閱https://en.wikipedia.org/wiki/X32_ABI。
- 添加系統(tǒng)調(diào)用lingyuecloudsyscall的函數(shù)聲明
在“l(fā)inux-3.10.1/include/linux/”目錄下的syscalls.h文件中添加函數(shù)聲明。
打開(kāi)syscalls.h,在倒數(shù)第二行添加下面內(nèi)容:
#vim include/linux/syscalls.h
asmlinkage long sys_lingyuecloudsyscall(int num);
如下圖所示:

- 重新編譯
- 內(nèi)核
編譯過(guò)程詳見(jiàn)http://www.lingyuecloud.com/Index/details/id/58.html——“Linux-3.10.1內(nèi)核的編譯和安裝”。 - 測(cè)試系統(tǒng)調(diào)用
編寫測(cè)試程序lingyuecloud_test.c:

編譯測(cè)試程序:
gcc -o lingyuecloud lingyuecloud_test.c
測(cè)試結(jié)果如下圖所示:

如果能夠看到上述結(jié)果,表示你的第一個(gè)自定義系統(tǒng)調(diào)用已經(jīng)添加成功。
本文轉(zhuǎn)載于 靈躍云 : 原文鏈接