解讀Linux操作系統內核源碼的好方法(2)
4.由此可見 , linux 的系統調用也象 dos 系統的 int 21h 中斷服務, 它把0x80 中斷作為總的入口, 然後轉到保存在sys_call_table 表中的各種中斷服務例程的入口地址 , 形成各種不同的中斷服務;
由以上源代碼分析可知, 要增加一個系統調用就必須在 sys_call_table 表中增加一項 ,
並在其中保存好自己的系統服務例程的入口地址,然後重新編譯內核,當然,系統服務例程是必不可少的。
由此可知在此版linux內核源程序中,與系統調用相關的源程序文件就包括以下這些:
arch/i386/boot/bootsect.S
arch/i386/Kernel/setup.S
arch/i386/boot/compressed/head.S
arch/i386/kernel/head.S
init/main.c
arch/i386/kernel/traps.c
arch/i386/kernel/entry.S
arch/i386/kernel/irq.h
include/asm-386/unistd.h
當然,這只是涉及到的幾個主要文件。而事實上,增加系統調用真正要修改文件只有include/asm-386/unistd.h和arch/i386/kernel/entry.S兩個。
C、對內核源碼的修改:
1.在kernel/sys.c中增加系統服務例程如下:
asmlinkage int sys_addtotal(int numdata)
{
int i=0,enddata=0;
while(i<=numdata)
enddata+=i++;
return enddata;
}
該函數有一個 int 型入口參數 numdata , 並返回從 0 到 numdata 的累加值;
當然也可以把系統服務例程放在一個自己定義的文件或其他文件中,只是要在相應文件中作必要的說明;
2.把 asmlinkage int sys_addtotal( int) 的入口地址加到sys_call_table表中:
arch/i386/kernel/entry.S 中的最後幾行源代碼修改前為:
... ...
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
.rept NR_syscalls-190
.long SYMBOL_NAME(sys_ni_syscall)
.endr
修改後為: ... ...
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
/* add by I */
.long SYMBOL_NAME(sys_addtotal)
.rept NR_syscalls-191
.long SYMBOL_NAME(sys_ni_syscall)
.endr