linux课程设计指导文档 联系客服

发布时间 : 星期二 文章linux课程设计指导文档更新完毕开始阅读b08d5cda7f1922791688e89f

3. 步骤3:修改相应内核文件 (1)

修改(添加)源代码

第一个任务是编写加到内核中的源程序,即将要加到一个内核文件中去的一个函数,该函数的名称应该是新的系统调用名称前面加上sys_标志。假设新加的系统调用为mycall(int number),在/usr/src/linux—2.6.18.2/kernel/sys.c文件中添加源代码,如下所示:

asmlinkage int sys_mycall(int number) {

return number; }

作为一个最简单的例子,我们新加的系统调用仅仅返回一个整型值。 说明:在以后的文档中,我们所指的/usr/src/linux—2.6.18.2/都是指内核路径,要根据自己的内核存放位置进行相应的改变。

(2)

连接新的系统调用

添加新的系统调用后,下一个任务是使Linux内核的其余部分知道该程序的存在。为了从已有的内核程序中增加到新的函数的连接,需要编辑两个文件。

在我们所用的Linux内核版本(2.6.18)中,首先要修改的文件是unistd.h(一般情况下有两个unistd.h需要修改):

/usr/src/linux—2.6.18.2/include/asm-i386/unistd.h /usr/include/asm/unistd.h

该文件中包含了系统调用清单,用来给每个系统调用分配一个唯一的号码。文件中每一行的格式如下:

#define __NR_name NNN

其中,name用系统调用名称代替,而NNN则是该系统调用对应的号码。应该将新的系统调用名称加到清单的最后,并给它分配号码序列中下一个可用的系统调用号。我们的系统调用如下:

#define __NR_sync_file_vange 314 #define __NR_tee 315 #define __NR_vmsplice 316

15

#define NR_syscalls 317

最后一行说明内核自身的系统调用号已经使用到316,共有317个(从0开始)。我们新添加的系统调用应该加到最后,并修改系统调用总数。修改如下:

#define __NR_sync_file_vange 314 #define __NR_tee 315 #define __NR_vmsplice 316

#define __NR_mycall 317 /*这是我们自己添加的系统调用*/

#define NR_syscalls 318

第二个要修改的文件是:

/usr/src/linux—2.6.18.2/arch/i386/kernel/syscall_table.S

在2.6版本以前,需要修改的是/usr/src/linux/arch/i386/kernel/entry.s,在该文件下有sys_call_table,直接进行修改。

在2.6版本后,entry.s文件中的sys_call_table独立出来,我们可以在该文件下看

到类似于#include\字样,说明我们正真需要修改syscall_table.s。 在syscall_table.s中有类似如下的清单:

.long sys_name

该清单用来对sys_call_table[]数组进行初始化。该数组包含指向内核中每个系统调用的指针。这样就在数组中增加了新的内核函数的指针。我们在清单上与系统调用号相对应的位置添加一行:

.long sys_mycall

必须注意添加的行的位置,否则容易造成内核编译的失败。

4. 步骤4:开始对新的内核进行编译

在2.6内核之前,编译内核需要如下命令: make mrproper

16

make dep make clean make bzImage make modules make modules_install

然后需要将新生成的System.map 和bzImage拷贝到/boot下,并建立连接。

在2.6中,这些已经得到简化,只要以下命令即可: make mrproper

make xconfig(可视化选项) make

make modules_install make install 说明:

其中make mrproper命令用来清除旧的配置等文件,避免编译内核时生成的文件不一致

make xconfig用于选择内核编译配置,事实上还有config,gconfig,menuconfig等选项可以选用。这一步选择很重要,必须选对,编译内核时才能得到正确结果。对于2.6.18.2版本来说,必须要注意的是选中ext3项。

【配置内核 配置内核的选项有N多,为了避免繁琐的配置,可以在 /boot 的目录下找到一个类似config-2.6.18-1.2798.fc的配置文件,将他copy到 /usr/src/linux-2.6.18.1/下,并改名 config;

[root@localhost linux-2.6.18.1]# make menuconfig 用户可以直接保存退出。】

make 编译新内核(完成了以前的make bzImage和make modules命令) make modules_install模块命令

make install 安装新内核(完成了以前需要手工进行的后处理工作)

如果执行成功,则在/boot/grub中的grub.conf中会出现新内核的选项。

17

至此,新内核已经建立,新添加的系统调用已经成为操作系统的一部分,重启后选用新内核即可测试该新的系统调用。

2.3. 对新加的系统调用进行测试

1. 旧版本的测试方法

在应用程序中使用新添加的系统调用mycall,为了测试,我们编写一个简单的例子test.c.

/* test.c */

#include

_syscall2(int,mycall,int,ret) //系统调用函数声明 main {

printf(\

}

在当前路径下编译执行该程序。

注意:由于要编译系统源程序以及使用系统调用,以上操作都应该在root用户下进行。

2. 新版本的测试方法

在2.6.18之后_syscallN(0~7)的定义与以前的版本不太一样,不再使用_syscallN宏了。 syscall调用接口从2.6.18开始移到应用层,原来内核中使用_syscallN宏的方式来声明函数原型的方法不再有效: 如声明:

_syscall1(int, sysinfo, struct sysinfo *, info); 不再需要,而是在程序中需要的时候直接调用: int syscall(int number, ...);

* 第一个number是后面要接的参数个数,不是该系统调用的参数个数; * number后面顺序接上该系统调用的所有参数即可

18