解讀Linux操作系統內核源碼的好方法(3)
3. 把增加的 sys_call_table 表項所對應的向量,在include/asm-386/unistd.h
中進行必要申明,以供用戶進程和其他系統進程查詢或調用:
增加後的部分 /usr/src/linux/include/asm-386/unistd.h 文件如下:
... ...
#define __NR_sendfile 187
#define __NR_getpmsg 188
#define __NR_putpmsg 189
#define __NR_vfork 190
/* add by I */
#define __NR_addtotal 191
4.測試程序(test.c)如下:
#include
#include
_syscall1(int,addtotal,int, num)
main()
{
int i,j;
do
printf("Please input a number\n");
while(scanf("%d",&i)==EOF);
if((j=addtotal(i))==-1)
printf("Error occurred in syscall-addtotal();\n");
printf("Total from 0 to %d is %d \n",i,j);
}
對修改後的新的內核進行編譯,並引導它作為新的操作系統,運行幾個程序後可以發現一切正常;在新的系統下對測試程序進行編譯(*注:由於原內核並未提供此系統調用,所以只有在編譯後的新內核下,此測試程序才能可能被編譯通過),運行情況如下:
$gcc -o test test.c
$./test
Please input a number
36
Total from 0 to 36 is 666
可見,修改成功;
而且,對相關源碼的進一步分析可知,在此版本的內核中,從/usr/src/linux/arch/i386/kernel/entry.S
文件中對 sys_call_table 表的設置可以看出,有好幾個系統調用的服務例程都是定義在/usr/src/linux/kernel/sys.c
中的同一個函數:
asmlinkage int sys_ni_syscall(void)
{
return -ENOSYS;
}
例如第188項和第189項就是如此:
... ...
.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 */
... ...
而這兩項在文件 /usr/src/linux/include/asm-386/unistd.h 中卻申明如下:
... ...
#define __NR_sendfile 187
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
#define __NR_vfork 190
由此可見,在此版本的內核源代碼中,由於asmlinkage int sys_ni_syscall(void) 函數並不進行任何操作,所以包括 getpmsg,
putpmsg 在內的好幾個系統調用都是不進行任何操作的,即有待擴充的空調用;
但它們卻仍然占用著sys_call_table表項,估計這是設計者們為了方便擴充系統調用而安排的;
所以只需增加相應服務例程(如增加服務例程getmsg或putpmsg),就可以達到增加系統調用的作用。