1、实验环境:
实验的环境为Ubuntu9.10系统,内核版本为2.6.31-21-generic。添加完系统调用后的内核版本命名为2.6.31-12。
2,实验步骤:
1)下载Linux内核:在终端中输入命令$sudo apt-get install linux-source。下载后的文件默认放在目录/usr/src下。
2) 将内核代码解压缩:例如下载的内核文件为linux-source-2.6.31.tar.bz2,运行解压命令tar –jxvf linux-source-2.6.31.tar.bz2。解压出的文件夹为/usr/src/linux-source-2.6.31。如下图:
3) 修改/usr/src/linux-source-2.6.31/kernel/sys.c文件,在文件末尾增加三个系统响应函数。函数实现如下:
asmlinkage int sys_mycall(int number)
{
printk("这是我添加的第一个系统调用");
return number;
}
asmlinkage int sys_addtotal(int number)
{
int i=0,enddate=0;
printk("这是我添加的第二个系统调用");
while(i<=number)
enddate+=i++;
return enddate;
}
asmlinkage int sys_three()
{
printk("这是我添加的第三个系统调用");
return 0;
}
4)在/usr/src/linux-source-2.6.31/arch/x86/kernel/syscall_table_32.S 中添加:.long sys_mycall。
5)在/usr/src/linux-2.6.31/arch/x86/include/asm/unistd_32.h中添加:#define __NR_mycall 序号(例如337),添加系统调用的入口参数(注意:其中会顺序定义入口参数的序号,添加的序号是在原有最大值的基础上+1);实现如下:
编译内核,命令依次如下:
首先切换到解压的内核目录下。
第一步:make mrproper //清除内核中不稳定的目标文件,附属文件及内核配置文件
第二步:make clean //清除以前生成的目标文件和其他文件
第三步:make oldconfig// 采用默认的内核配置(使用make menuconfig可以自己配置编译选项)
第四步:make bzImage //编译内核
第五步:make modules //编译模块
第六步:make modules_install// 安装模块
编译完成后,设置采用新内核启动。
我编译成功的内核版本号命名为2.6.31.12
运行命令:
cp /usr/src/linux-source-2.6.31/arch/i386/boot/
bzImage /boot/vmlinuz-2.6.31.12-mykernel(注意:2.6.31.12为你编译的内核版本。)
mkinitramfs -o initrd.img-2.6.31.12 2.6.31.12
//执行目录/usr/src/linux-source-2.6.31/下
cp /usr/src/linux-source-2.6.31/initrd.img-2.6.31.12 /boot/ initrd.img-2.6.31.12
增加引导菜单项,配置启动项文件/boot/grub/grub.cfg。添加的配置如下:
完成后执行终端命令sudo update-grub2,之后重启,终端输入uname -a检查你的内核版本是否是你编译的版本2.6.31.12 。
编写测试函数:我的测试函数如下:
/*~~~~~~~~~~~~~~~test1.c~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include<stdio.h>
int main()
{
int tmp;
tmp=syscall(337,1);
printf("/n");
if(tmp==1)
{
printf("第1次系统调用成功!/n");
}
tmp=syscall(338,5);
printf("/n");
if(tmp==15)
{
printf("第2次系统调用成功!/n");
}
tmp=syscall(339);
printf("/n");
if(tmp==0)
{
printf("第3次系统调用成功!/n");
}
}
编译,运行。在终端输入dmesg -c可显示函数的输出内容。
总结:
由于使用了系统调用,编译和执行程序时,用户都应该获得超级用户权限。而且grub.cfg默认是没有写权限的,需要修改是有写权限,为了系统安全,在配置完文件后不要忘了再将权限改回来。