|
增加系統(tǒng)調(diào)用
在實(shí)際編程中,尤其是當(dāng)我們需要增加或完善系統(tǒng)功能的時(shí)候,我們經(jīng)常會(huì)用到系統(tǒng)調(diào)用函數(shù)。系統(tǒng)調(diào)用函數(shù)通常由用戶進(jìn)程在用戶態(tài)下調(diào)用,內(nèi)核通過(guò)system_call 函數(shù)響應(yīng)系統(tǒng)調(diào)用產(chǎn)生的軟中斷,在正確訪問(wèn)核心棧、系統(tǒng)調(diào)用開(kāi)關(guān)表之后陷入到操作系統(tǒng)內(nèi)核中進(jìn)行處理。
系統(tǒng)調(diào)用是用戶進(jìn)程由用戶態(tài)切換到核心態(tài)的一種常見(jiàn)方式。利用編寫(xiě)系統(tǒng)調(diào)用函數(shù)來(lái)直接調(diào)用了部分操作系統(tǒng)內(nèi)核代碼,也是Linux內(nèi)核編程者必修之功。下面筆者以在Linux中創(chuàng)建一個(gè)名為print_info的系統(tǒng)調(diào)用函數(shù)為例,來(lái)說(shuō)明如何為內(nèi)核增加系統(tǒng)調(diào)用。
需要以下幾個(gè)基本步驟:
1、編寫(xiě)系統(tǒng)調(diào)用函數(shù) 編輯sys.c文件: # cd /usr/src/linux/kernel # vi sys.c 在文件的最后增加一個(gè)系統(tǒng)調(diào)用函數(shù): asmlinkage int sys_print_info(int testflag) { printk(" Its my syscall function!n"); return 0; } 該函數(shù)有一個(gè)int型入口參數(shù)testflag,并返回整數(shù)0。
2、修改與系統(tǒng)調(diào)用號(hào)相關(guān)的文件 編輯入口表文件: # cd /usr/src/linux/arch/i386/kernel # vi entry.S 把函數(shù)的入口地址加到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 */ .long SYMBOL_NAME(sys_print_info) /* added by I */ .rept NR_syscalls-191 .endr 修改相應(yīng)的頭文件: # cd /usr/src/linux/include/asm # vi unistd.h 把增加的sys_call_table表項(xiàng)所對(duì)應(yīng)的向量,在include/asm/unistd.h中進(jìn)行必要申明,以供用戶進(jìn)程和其他系統(tǒng)進(jìn)程查詢或調(diào)用。 #define __NR_putpmsg 189 #define __NR_vfork 190 #define __NR_print_info 191 /* added by I */
3、編譯內(nèi)核,再重啟動(dòng)
4、測(cè)試 編寫(xiě)用戶測(cè)試程序(test.c): # vi test.c #include #include extern int errno; _syscall1(int,print_info,int,testflag) main() { int i; i= print_info(0); if(i==0) printf("i=%d , syscall success!n",i); } 如果要在用戶程序中使用系統(tǒng)調(diào)用函數(shù),那么在主函數(shù)main前必須申明調(diào)用_syscall,其中1 表示該系統(tǒng)調(diào)用只有一個(gè)入口參數(shù),第一個(gè)int 表示系統(tǒng)調(diào)用的返回值為整型,print_info為系統(tǒng)調(diào)用函數(shù)名,第二個(gè)int 表示入口參數(shù)的類型為整型,testflag為入口參數(shù)名。 編譯測(cè)試程序: # gcc -o test test.c 執(zhí)行測(cè)試程序: # ./test Its my syscall function! i=0, syscall success! ok!!!增加系統(tǒng)調(diào)用函數(shù)成功! 以上步驟在pentium Ⅲ/64M/20G、Red Hat Linux 6.0(2.2.5-15)機(jī)上測(cè)試通過(guò)。
|