实验四 增加Linux系统调用
实验目的:学习如何产生一个系统调用以及怎样同过往内核中增加一个新函数从而在内核空间中实现对用户空间的读/写。
注意:直接看实验步骤即可,4.2问题陈述了解即可,不怎么重要
下载一个新内核,可以去下方的网站:
4.1 介绍
从这个实验开始,我们开始真正的接触Linux内核。Linux系统调用是用于导出可供用户空间程序调用的内核函数的名称,它们不能像普通的libc库中的函数一样调用,而必需通过0x80陷阱进核调用。这样,如果用户创建了一个新的内核函数,就必须在内核陷阱表中创建一个新的表项来引用该函数。
所有的内核函数入口表集中在/user/src/linux/arch/i386/kernel/entrys.S中。该表具有如下所示的形式:
.data
ENTRY(sys_call_table) /* 入口 */
.long SYMBOL_NAME(sys_ni_call) /* 0, 空项 */
.long SYMBOL_NAME(sys_exit) /* 1 */
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
.long SYMBOL_NAME(sys_open) /* 5 */
…
.long SYMBOL_NAME(sys_signalstack)
.long SYMBOL_NAME(sys_sendfile)
…
.long SYMBOL_NAME(sys_ni_call) /* 空项 */
.long SYMBOL_NAME(sys_ni_call)
…
.endr /* 结束 */
表项1包含了exit()系统调用(其实现为sys_exit()内核函数),表项2包含了fork()系统调用,以此类推。
系统调用是在sys_call_table中定义的,这样当增加一个新的系统调用是,就必须在这个表中增加一个新的表项。编辑该文件,增加自己的系统调用如下:
…
.long SYMBOL_NAME(sys_ni_call) /* 222 */
.long SYMBOL_NAME(sys_my_new_call) /223,用户自定义系统调用/
…
注意,linux系统自身保留了221个系统调用。这就意味着,你自己增加的系统调用至少要在第222项以后开始,还要小于256,(内核2.4的有的版本可能多达237个,因此,进建议你选择较为靠后的序号)。另外,这个操作也只有超级用户才有权限完成。
为了使普通的C函数也能够在重新编译内核之后也能调用你的内核函数,最好还要编辑 内核目录下的include/asm/unistd.h文件。
#define __NR_exit 1
#def