Linux操作系统精讲大连理工大学软件学院邱铁综合楼413,Tel:0411-87571632E_mail:qiutie@dlut.edu.cn参考教材:《Linux应用与开发典型实例精讲》邱铁、于玉龙、徐子川编著.清华大学出版社.2010.5第15章系统调用学习本章要达到的目标:1.理解Linux系统调用机制的实现原理;2.基于Linux昀新内核2.6.30,分析Linux操作系统系统调用的代码结构;3.掌握向Linux系统增加自己的系统调用的方法。15.1系统调用原理系统调用是操作系统内核提供的、功能相对较强的一系列函数。这些函数是在的内核码中实现的,并通过某种接口形式,将这些函数提供给用户来进行调用。为了保证操作系统内核的安全与系统的稳定,操作系统提供了系统调用。系统调用一般的过程是,进程使用寄存器中适当的值跳转到内核中事先定义好的只读的代码段中执行。在x86体系结构的计算机中,系统调用由软中断0x80来实现系统调用过程Linux内核会进行中断服务的处理,并执行system_call函数,进入系统调用入口的公共处理函数,在这个函数中会按照通过寄存器eax传递的内容来识别所对应处理所有的系统调用。在进入系统内核后后,使用system_call_table和eax中包含的索引来执行真正的系统调用。从系统调用中返回后,昀终执行syscall_exit,并调用resume_userspace返回用户空间。15.2系统调用函数分析Linux内核版本中有一个entry.S文件,但是新的版本中分为了entry_32.S和entry_64.S,表示支持不同位数的体系结构的计算机,并且在文件内部用了大量的宏代替了原来的处理器指令。15.2.1系统调用入口函数entry_32.S文件在Linux内核2.6.30中的/usr/src/linux-2.6.30/arch/x86/kernel目录下,具体分析参见教材第247页当在程序代码中用到系统调用时,编译器会按照系统调用号将系统调用宏展开,展开后的代码实际上是将系统调用号放入eax,然后用软中断int0x80使处理器转向系统调用入口,并进行查找系统调用表,进而由内核调用真正的系统调用功能函数。15.2.2系统调用表对于x8632位体系结构的系统调用表位于/arch/x86/kernel/syscall_table_32.S文件中系统调用统一定义为sys_xxxxx(其中,xxxxx系统调用函数名)syscall_table_32.S文件源码如下ENTRY(sys_call_table).longsys_restart_syscall/*0系统调用是为系统重新启动时设计的*/.longsys_exit…………………….longsys_epoll_create1.longsys_dup3/*330*/.longsys_pipe2.longsys_inotify_init1.longsys_preadv.longsys_pwritev15.3添加系统调用实例训练1.下载2.6.30内核,解压到/usr/src目录中。2.添加系统调用表将.longsys_mysyscall添加到arch/x86/kernel/syscall_table_32.S中昀后一行3.添加系统调用号对于32位x86架构请将系统调用号添加到arch/x86/include/asm/unistd_32.h中对于64位x86架构请将系统调用号添加到include/asm-x86/unistd_64.h中4.编写系统调用对于32位x86处理器架构请将以上一段代码添加到arch/x86/kernel/sys_i386_32.c的昀后一行,而对于64位架构将其添加到arch/x86/kernel/sys_x86_64.c中的昀后一行。asmlinkageintsys_mysyscall(charN){chari;intNx=1;if(N==0)returnNx;for(i=1;i=N;i++)Nx=Nx*i;returnNx;}5.按照第12章的步骤重新编译内核。6.编译成功后,重启系统进入新编译的内核。7.编写测试程序syscall_test.c,#includestdio.h#includelinux/unistd.h#define__NR_mysyscall335//自定义的系统调用编号intmain(){intNumber,Factorial;printf(Pleaseinputanumber\n);while(scanf(%d,&Number)==EOF);Factorial=syscall(__NR_mysyscall,Number);if(Factorial1)printf(Erroroccurredinmysyscall\n);printf(%dFactorialis%d\n,Number,Factorial);return0;}测试程序输出结果思考与练习1、深入理解Linux系统调用的原理与过程。2、下载当前昀新版本的Linux内核,加入自己的系统调用后,重新编译内核并安装,再编写一个测试函数进行验证其正确性。3、在32位体系结构下与64位体系结构的计算机下添加自定义的Linux系统调用的流程是否相同?如果不同,请指出不同点有哪些。4、可以考虑用模块的方法来为现有的Linux系统添加一个系统调用。