参考文献:
Chapter 4, Linux kernel development second edition
深入LINUX内核:为你的LINUX增加一条系统调用
充分利用LINUX开放源码的特性,我们可以轻易地对它进行修改,使我们能够随心所欲驾驭LINUX,完成一个真正属于自己的操作系统,这种感觉使无与伦比的,下面通过为LINUX增加一个系统调用来展示LINUX作为一个开放源码操作系统的强大魅力。
首先,让我们简单地分析一下LINUX中与系统调用的相关的部分:
LINUX的系统调用的总控程序是system_call,它是LINUX系统中所有系统调用的总入口,这个system_call是作为一个中断服务程序挂在中断0x80上,系统初始化时通过void init trap_init(void)调用一个宏set_system_ gate(SYSCALL_VERCTOR,&system_call)来对IDT表进行初始化,在0x80对应的中断描述符处填入system_call函数的地址,其中宏SYSCALL_VERCTOR就是0x80。
当发生一条系统调用时,由中断总控程序保存处理机状态,检查调用参数的合法性,然后根据系统调用向量在sys_call_table中找到相应的系统服务例程的地址,然后执行该服务例程,完成后恢复中断总控程序所保存的处理机状态,返回用户程序。
系统服务例程一般定义于kernel/sys.c中,系统调用向量定义在include/asm-386/unistd.h中,而sys_call _table表则定义在arch/i386/kernel/entry.S文件里。
现在我们知道增加一条系统调用我们首先要添加服务例程实现代码,然后在进行对应向量的申明,最后当然还要在sys_call_table表中增加一项以指明服务例程的入口地址。
OK,有了以上简单的分析,现在我们可以开始进行源码的修改,假设我们需要添加一条系统调用计算两个整数的平方和,系统调用名为add2,我们需要修改三个文件:kernel/sys.c , arch/i386/kernel/entry.S 和 include/asm-386/unistd.h。
1、修改kernel/sys.c ,增加服务例程代码:
asmlinkage int sys_add2(int a , int b)
{
int c=0;
c=a*a+b*b;
return c;
}
2、修改include/asm-386/unistd.h ,对我们刚才增加的系统调用申明向量,以使用户或系统进程能够找到这条系统调用,修改后文件如下所示:
.... .....
#define _NR_sendfile 187
#define _NR_getpmsg 188
#define _NR_putmsg 189
#define _NR_vfork 190
#define _NR_add2 191 /* 这是我们添加的部分,191即向量 */
3、修改include/asm-386/unistd.h , 将服务函数入口地址加入 sys_call_table,首先找到这么一段:
.... .....
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams 1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams 2 */
.long SYMBOL_NAME(sys_vfork) /*190 */
.rept NR_syscalls-190
修改为如下:
.... .....
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams 1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams 2 */
.long SYMBOL_NAME(sys_vfork) /*190 */
.long SYMBOL_NAME(sys_add2) <=我们的系统调用
.rept NR_syscalls-191 <=将190改为191
OK,大功告成,现在只需要重新编译你的LINUX内核,然后你的LINUX就有了一条新的系统调用int add2(int a, int b)。
urg
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment