当前位置:文档之家› linux实验_添加系统调用-完整版

linux实验_添加系统调用-完整版

实验一添加一个新的系统调用
一、实验目的
理解操作系统内核与应用程序的接口关系;加深对内核空间和用户空间的理解;学会增加新的系统调用。

二、实验内容与要求
首先增加一个系统调用函数,然后连接新的系统调用,重建新的Linux内核,用新的内核启动系统,使用新的系统调用(2.4内核和2.6内核任选一个)
三、实验指导(2.6版本)
⑴获得源代码(本次实验的内核版本是2.6.22.5,必须是root用户)
1.从教育在线上下载内核源代码到本地磁盘;保存在/usr/src目录下
2.进入终端,输入命令cd /usr/src 进入/usr/src目录(可以输入ls命令会发现目录下有一个名为LINUX_2_6_22_5.TAR.BZ2的压缩文件)
3.当前目录下(/usr/src)输入命令tar –xjvf LINUX_2_6_22_5.TAR.BZ2 解压缩源代码,命令执行完毕后,会出现/usr/src/linux-2.6.22.5文件夹
4.修改文件夹下的3个文件
第一,编辑/usr/src/linux-版本号/kernel/sys.c文件,添加函数:
asmlinkage long sys_mycall(long number)
{
printk(“call number is %d\n”,number);
return number;
}
第二,修改/usr/src/linux-版本/include/asm-i386/unistd.h
添加一行#define __NR_mycall 324 到当前的最大系统调用号之后,比如原来最大的是323,在323的这一行之后加上一行#define __NR_mycall 324
修改#define NR_systemcalls 的值,改成原来的值+1,比如原来是324 改成325
第三,编辑/usr/src/linux-版本/arch/i386/kernel/syscall_table.S,在文件最后加上一行:.long sys_mycall
5.重新编译内核
在终端输入命令,进入源代码文件夹,cd /usr/src/linux-2.6.22.5 依次执行如下命令:make mrproper
make clean
make xconfig (自己配置内核,出现图形对话框后,直接点保存,关闭)
make
(耗时最长,大约20分钟)
make modules_install (安装模块)
以上命令执行完毕后,会在当前目录下生成一个名为System.map的文件,会在/usr/src/linux-版本号/arch/i386/boot/下生成一个bzImage文件。

在终端执行以下命令:
cp /usr/src/linux-版本号/arch/i386/boot/bzImage /boot/vmlinuz-版本号(拷贝内核镜像)cp /usr/src/linux-版本号/System.map /boot/System.map-版本号(拷贝符号表)
cd /boot (进入/boot目录)
mkinitrd initrd-版本号.img 版本号(如mkinitrd initrd-2.6.22.5.img 2.6.22.5)(生成临时根文件)
6.编辑启动配置文件grub
编辑/boot/grub/grub.conf 在grub.conf文件中,每一个title标签表示一个启动项,仿照第一段title的写法,编写新内核的启动项,其中kernel和initrd使用新拷贝过来的vmlinz—版本号文件和initrd-版本号.img文件。

(可以先复制一段title的内容,修改title后面的启动名称,修改kernel 和initrd 后面指定的启动文件,如下图所示,选中的内容是修改后的)
图1 原来的grub配置文件
图2 修改后的grub配置文件
7.重新启动系统,使用新生成的内核。

8.编写测试程序,测试新系统调用。

testcall.c
int main()
{
syscall(324,100); /*324是新添加的系统调用号,100是参数*/
return 0;
}
终端编译gcc testcall.c –o testcall
运行./testcall
查看结果:终端运行命令dmesg 会看到在最后一行输出call number is 100
四、2.4内核下添加系统调用的方法(添加系统调用必须是root用户)
1.获得linux源代码
在linux系统的/usr/src目录下有系统的源代码。

(如果没有,可以先下载,然后解压到此目录下),解压完毕后,源代码的目录就是/usr/src/linux-版本号
2.添加自定义的系统调用实现函数
编辑/usr/src/linux-版本号/kernel/sys.c文件,添加函数:
asmlinkage long sys_mycall(long number)
{
printk(“call number is %d\n”,number);
return number;
}
3.添加系统调用号
编辑/usr/src/linux-版本号/include/asm-i386/unistd.h文件,在最大系统调用号的最后添加一项
#define __NR_mycall 259 (假设当前的最大系统调用号是258)
4.在系统调用入口表中添加相应的项。

编辑/usr/src/linux/arch/i386/kernel/entry.S 文件
添加long SYMBOL_NAME(sys_mycall)
5.重新编译内核
在源代码目录下有一个Makefile文件,(/usr/src/linux-版本号/Makefile),Makefile 文件的前四行是内核的版本号,如下:
VERSION=2
PATCHLEVEL=4
SUBLEVEL=20
EXTRAVERSION=-8 (假设内核版本是2.4.20-8)
在修改内核后,编译内核之前,可以修改Makefile的内核版本号信息,比如可以将EXTRAVERSION项改成-8a,那么重新编译内核后,新内核的版本号将是2.4.20-8a
以下是编译内核的步骤:
首先进入源代码目录/usr/src/linux-版本号,依次运行以下命令:
make mrproper 确保没有不正确的.o文件及文件的相互依赖
make clean 清除旧的编译结果
make config 或者make menuconfig 或者make xconfig //配置内核
make dep 生成依赖关系
make bzImage 编译内核映象
make modules 编译内核模块
make modules_install 安装内核模块
以上命令成功完成后,将生成的内核镜像文件和符号表拷贝到/boot目录下。

cp arch/i386/boot/bzImage /boot/vmlinuz-版本号(拷贝内核镜像)
cp System.map /boot/System.map-版本号(拷贝符号表)
cd /boot (进入/boot目录)
mkinitrd initrd-版本号.img 版本号(如mkinitrd initrd-2.4.20-8a.img 2.4.20-8a)(生成临时根文件)
6.编辑启动配置文件grub
编辑/boot/grub/grub.conf 在grub.conf文件中,每一个title标签表示一个启动项,仿照每一段title的写法,编写新内核的启动项,其中kernel和initrd使用新拷贝过来的vmlinz—版本号文件和initrd-版本号.img文件。

7.重新启动系统,进入新生成的内核。

8.编写测试程序,测试新系统调用。

testcall.c
int main()
{
syscall(259,100); /*259是新添加的系统调用号,100是参数*/
return 0;
}
终端编译gcc testcall.c –o testcall
运行./testcall
查看结果dmesg 会看到输出call number is 100。

相关主题