参考文献:
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
Showing posts with label Kernel. Show all posts
Showing posts with label Kernel. Show all posts
Friday, October 31, 2008
Saturday, October 25, 2008
Rebuild the kernel
1. Download the kernel from http://www.kernel.org
tar xvzf linux-x.y.z.tar.gz
Read the READ me file at the root directory.
2. make menuconfig
3. make modules_install
4. make install
5. modify grub configuration file /boot/grub/menu.lst if it is not modified by step 4.
6. reboot and select the new kernel
title SUSE Linux Enterprise Desktop 10
root (hd0,4)
kernel /boot/vmlinuz root=/dev/sda5
initrd /boot/initrd
The initial ramdisk, or initrd is a temporary file system commonly used by the Linux kernel during boot. The initrd is typically used for making preparations before the real root file system can be mounted.
tar xvzf linux-x.y.z.tar.gz
Read the READ me file at the root directory.
2. make menuconfig
3. make modules_install
4. make install
5. modify grub configuration file /boot/grub/menu.lst if it is not modified by step 4.
6. reboot and select the new kernel
title SUSE Linux Enterprise Desktop 10
root (hd0,4)
kernel /boot/vmlinuz root=/dev/sda5
initrd /boot/initrd
The initial ramdisk, or initrd is a temporary file system commonly used by the Linux kernel during boot. The initrd is typically used for making preparations before the real root file system can be mounted.
Subscribe to:
Posts (Atom)