linux系统调用接口.ppt_第1页
linux系统调用接口.ppt_第2页
linux系统调用接口.ppt_第3页
linux系统调用接口.ppt_第4页
linux系统调用接口.ppt_第5页
已阅读5页,还剩32页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第10章系统调用接口,系统调用接口的功能,内核为用户与硬件设备(例如:CPU,磁盘,打印机等)交互提供了一个接口。该接口被称为系统调用接口。它的功能是:,使用户编程更加容易,把用户从学习硬件设备的低级编程特性中解放出来。可以极大提高系统的安全性,因为内核接收用户请求之前,可以检查其合法性。使用系统调用接口使得程序具有良好的可移植性。,10.1API和系统调用,UNIX操作系统为编程员提供了应用编程接口(API)。在API提供的libc标准函数库中,一部分是用户态的库函数,另一部分是系统调用。库函数和系统调用的区别是:,库函数是一个函数定义,说明如何获得一个给定的服务,库函数代码不属于内核。系统调用是通过软件中断(int指令)向内核发出的一个明确服务请求,提供服务的代码属于内核代码。,为了区别库函数和系统调用,libc标准C库中,每个系统调用都有一个封装例程(wrapperroutine)。应用程序通过这个封装例程来引用API函数库中的系统调用。用户执行一个系统调用时,内核通过(int0 x80)软件中断或调用门从用户空间进入内核空间,这就是所谓的模式转换。CPU切换到内核态开始执行与系统调用相对应内核函数。执行结束后内核将执行结果和控制权还给用户进程。图10-6给出调用系统调用的示意图。,调用一个系统调用示意图,printf(),在应用程序中调用系统调用,在libc库中的封装例程,用户态,system_call:sys_printf()ret_from_sys_calliret,sys_printf(),内核态,系统调用处理机制,系统调用服务例程,图10-6系统调用示意图,10.2模式转换的硬件处理,在i386中,完成系统调用接口模式转换的硬件是陷阱门和调用门,软件是int0 x80指令或调用指令,下面分析陷阱门技术。注:调用门技术请读者见教材P227(因为通常情况下,在Linux内核没有使用调用门)这里不做介绍。,10.2.1陷阱门模式转换,系统调用属于软件中断。i386保护模式下的软件中断使用陷阱门描述符。,使用陷阱门执行软件中断,不会影响硬件中断请求。,Linux为系统调用设置的陷阱门向量号是128,即16进制的“80H”。i386使用的陷阱(trap)指令是int$0 x80。图10-1给出陷阱门进行模式转换的示意图。,系统调用的服务例程system_call()处理程序,中断描述符表offsetdpl01111selectoroffsetGATE0baseaddrlimitdplbseaddrbaseaddrlimit,IDT的基址,限长,selector,baseaddrlimit,中断描述符寄存器IDTR,CS(代码段寄存器),代码段描述符高速缓存,system_call()起始地址,物理存储器,一个门描述符占8B。,在GDT或LDT中的代码段描述符。,陷阱门80H,图10-1陷阱门模式转换图,10.3系统调用接口,i386保护模式下,系统调用接口由软件和硬件共同协作完成。下面讲解系统调用处理程序system_call的工作原理。,10.3.1初始化系统调用,系统启动内核初始化期间调用trap_init函数建立IDT表中向量号为128对应的表项(8个字节的陷阱门描述符)。代码如下:,set_system_gate(SYSCALL_VECTOR,#defineSYSCALL_VECTOR0 x80,上面两行代码等效于下面的语句:,set_system_gate(0 x80,set_system_gate()初始化80H开始的8个字节的陷阱门描述符。步骤如下:,将内核代码段选择符_KERNEL_CS装入80H陷阱门的2、3两个字节。将system_call()可执行代码的第一条指令偏移量装入80H陷阱门的0、1、6和7共4个字节中。将15添入80H陷阱门类型号字段,说明这是一个陷阱门。将门描述符DPL字段设置为3,允许用户进程调用system_call()程序。,10.3.2系统调用执行流程,图10-4系统调用的执行流程,10.3.3封装例程,system_call()是系统调用入口点。系统调用主要供用户编程使用,但也可以被内核态线程调用。为了简化系统调用的调用过程,Linux提供的封装例程是一组预处理宏。共定义了6个宏:,从_syscall0到_syscall5,#define_syscallN(type,name,type1,arg1,type2,arg2,type3,arg3,.)typename(type1arg1,type2arg2,type3arg3,.)long_res;_asm_volatile(int$0 x80:=a(_res):0(_NR_#name),b(long)(arg1),c(long)(arg2),d(long)(arg3);._syscall_return(type,_res);,程序清单10-1封装例程:,程序清单10-1给出封装例程的定义:,封装例程的解释,_syscallN中的“N”是系统调用的参数个数。,前两个字符串指明系统调用的返回值类型和名字;紧随其后的每一对参数指明该系统调用所需要的其他参数的类型和名字。,fork()系统调用无参数,它的封装例程是:,系统调用名字,调用参数个数,返回类型值,_syscall0(int,fork),write()系统调用有3个参数,其封装例程宏指令格式是:,可以按照程序清单10-1把_syscall3(int,write,)宏展开成下面的代码:,_syscall3(int,write,int,fd,constchar*,buf,unsignedint,count),参数个数,其中,兰色字符串是write()系统调用需要的3对参数。,intwrite(intfd,constchar*buf,unsignedintcount)long_res;_asm_volatile(int$0 x80:=a(_res):0(_NR_write),b(long)fd),c(long)buf),d(long)count);if(unsignedlong)_res=(unsignedlong)-125)errno=-_res;_res=-1;return(int)_res;,它是系统调用号,来自_syscall3()的第2个参数,对这个函数进行编译,生成的汇编代码如下:,write:pushl%ebx;将ebx内容进栈movl8(%esp),%ebx;将第一个参数放入ebxmovl12(%esp),%ecx;将第二个参数放入ecxmovl16(%esp),%edx;将第三个参数放入edxmovl$4,%eax;将_NR_write放入eaxint$0 x80;执行系统调用cmpl$-125,%eax;检测返回码jbe.L1;如无错跳转negl%eax;求eax的补码movl%eax,errno;将结果放入errnomovl$-1,%eax;将eax置为-1.L1:popl%ebx;从堆栈弹出ebxret;返回调用程序,从汇编代码中可知传递给write()的参数是在执行int0 x80指令之前就被装入到CPU各个寄存器中。如果eax中的返回值为-1到-125之间,将被解释为错误码。否则返回eax中的值,表明调用成功。,10.3.4系统调用号与系统调用表,system_call()函数是内核中所有系统调用的唯一入口点,因此内核要为每个系统调用编一个序号,这个序号叫做系统调用号。从上一节的封装例程代码中可以看到,执行int0 x80之前,系统调用号已被放在eax中。程序清单10-2给出了部分系统调用号。,#define_NR_exit1#define_NR_fork2#define_NR_read3#define_NR_write4#define_NR_open5#define_NR_close6#define_NR_removexattr235#define_NR_lremovexattr236#define_NR_fremovexattr237,程序清单10-2系统调用号,系统调用表,系统调用表是指向各系统调用函数指针组成的表。系统调用号是系统调用表中各表项的相对偏移量。执行system_call()时,根据eax中的系统调用号,定位该系统调用函数在系统调用表(sys_call_table)中的准确位置。程序清单10-3给出了部分系统调用表。,.dataENTRY(sys_call_table).longSYMBOL_NAME(sys_ni_syscall)/0-oldsetup()/systemcall.longSYMBOL_NAME(sys_exit).longSYMBOL_NAME(sys_fork).longSYMBOL_NAME(sys_read).longSYMBOL_NAME(sys_write).longSYMBOL_NAME(sys_open)/5,程序清单10-3系统调用表,10.3.5system_call的执行过程,系统执行int$0 x80指令进行模式转换时,核心栈的布局如图10-5所示。,ENTRY(system_call)pushl%eax/saveorig_eax,首先保存EAX寄存器的内容。SAVE_ALL/保存各通用寄存器的内容。GET_CURRENT(%ebx)/获取调用进程的task_struct结构的指针。cmpl$(NR_syscalls),%eax/检测系统调用是否合法系统调用。jaebadsys/如果该系统调用号越界则跳转到标号badsys处。testb$0 x20,flags(%ebx)/检测是否设置了PF_TRACESYS标志。jnetracesys/如果设置了PF_TRACESYS标志则跳转到标号tracesys处。call*SYMBOL_NAME(sys_call_table)(,%eax,4)/这里是调用并执行该/系统调用函数的地方movl%eax,EAX(%esp)/savethereturnvalue,系统调用返回,/返回值进栈保存。ret_from_sys_call:,函数system_call()的源代码如下:,函数system_call()是所有系统调用的入口点。在源代码中的调用语句是:,call*SYMBOL_NAME(sys_call_table)(0,%eax,4),该语句调用与系统调用号(在eax中)相对应的服务例程。系统调用表的每一个表项占4个字节,因此把系统调用号乘以4,再加上系统调用表的基址,就找到了指向该服务例程的地址,也就找到了要执行的系统调用函数。,里边是系统调用号,当服务例程执行结束时,可以从eax中获得返回值,并把这个返回值进栈保存。当进程恢复到自己的用户态执行时,就可以在eax中找到该系统调用的返回值。,注:由于lcall7代码很少使用,所以不在PPT中讲解。,10.5添加新系统调用实例,通过学习向内核添加一个新系统调用的过程,进一步理解系统调用的基本原理。,实例:新系统调用的功能是获取系统当前系统时间并显示在屏幕上。步骤如下:,编写新系统调用源程序,新系统调用的名称为:intptimeofday(structtimeval*tv,structtimezone*tz);新系统调用的源程序如下:,#includeexternstructtimezonesys_tz;asmlinkageintsys_ptimeofday(structtimeval*tv,structtimezone*tz)if(tv)structtimevalktv;do_gettimeofday(,ptimeofday.c程序,连接新的系统调用,将ptimeofday.c代码添加到/usr/linux/kernel/sys.c文件中,同时需要重新编辑2个文件:,在文件/usr/src/linux/include/asm/unistd.h中为新系统调用分配一个系统调用号为239。即在表10-2中的最后再添加一行:,#define_NR_ptimeofday239,在文件/usr/src/linux/arch/asm/kernel/entry.S中,即在表10-3中的最后再添加一行:,.longSYMBOL_NAME(sys_ptimeofday),编译新的Linux内核。编译内核要以超级用户身份登录,命令行如下:,#makexconfig#makedep#makebzImage,编译结束后,系统将产生一个新压缩的内核映像文件:,#usr/src/linux/arch/boot/bzImage,为了安装新系统内核,应该将上面产生的新内核映像文件拷贝到/boot/目录下:,#cpusr/src/linux/arch/boot/bzImage/boot/bzImage-new,启动新的内核操作系统:,如果你的机器使用grub加载OS,可参照教材表8-2内容修改/etc目录下的grub.conf文件。如果使用lilo加载OS,需要在已有的系统中修改/etc/lilo.conf文件。可参照表10-1,原有的/etc/lilo.conf文件修改后的/etc/lilo.conf文件promptprompttimeout=50timeout=50default=linuxdefault=linuxboot=/dev/had7boot=/dev/had7map=/boot/mapmap=/boot/mapinstall=/boot/boot.binstall=/boot/boot.bmassage=/boot/messagemassage=/boot/messagelba32lba32image=/boot/vmlinuz-2.4.18im

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论