Linux操作系统分析6 syscall.ppt

上传人:s****8 文档编号:82793105 上传时间:2023-03-26 格式:PPT 页数:38 大小:920.50KB
返回 下载 相关 举报
Linux操作系统分析6 syscall.ppt_第1页
第1页 / 共38页
Linux操作系统分析6 syscall.ppt_第2页
第2页 / 共38页
点击查看更多>>
资源描述

《Linux操作系统分析6 syscall.ppt》由会员分享,可在线阅读,更多相关《Linux操作系统分析6 syscall.ppt(38页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、Linux操作系统分析操作系统分析中国科学技中国科学技术术大学大学计计算机系算机系陈陈香香兰兰(051287161312)Autumn 2010系统调用系统调用系统调用的意义系统调用的意义操作系统为用户态进程与硬件设备进行交互提供了一组接口系统调用把用户从底层的硬件编程中解放出来极大的提高了系统的安全性使用户程序具有可移植性2023/1/23Linux OS AnalysisAPI和系统调用和系统调用应用编程接口(application program interface,API)和系统调用是不同的API只是一个函数定义系统调用通过软中断向内核发出一个明确的请求Libc库定义的一些API引用了

2、封装例程(wrapper routine,唯一目的就是发布系统调用)一般每个系统调用对应一个封装例程库再用这些封装例程定义出给用户的API2023/1/24Linux OS Analysis不是每个API都对应一个特定的系统调用。API可能直接提供用户态的服务如,一些数学函数一个单独的API可能调用几个系统调用不同的API可能调用了同一个系统调用返回值大部分封装例程返回一个整数,其值的含义依赖于相应的系统调用-1在多数情况下表示内核不能满足进程的请求Libc中定义的errno变量包含特定的出错码2023/1/25Linux OS Analysis系统调用程序及服务例程系统调用程序及服务例程当用

3、户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数。在Linux中是通过执行int$0 x80来执行系统调用的,这条汇编指令产生向量为128的编程异常(回忆,trapinit中系统调用入口的初始化)Intel Pentium II中引入了sysenter指令(快速系统调用),2.6已经支持(本课程不考虑这个)传参:内核实现了很多不同的系统调用,进程必须指明需要哪个系统调用,这需要传递一个名为系统调用号系统调用号的参数使用eax寄存器2023/1/26Linux OS Analysis所有的系统调用返回一个整数值。正数或0表示系统调用成功结束负数表示一个出错条件这里的返回值与封

4、装例程返回值的约定不同内核没有设置或使用errno变量封装例程在系统调用返回取得返回值之后设置这个变量当系统调用出错时,返回的那个负值将要存放在errno变量中返回给应用程序2023/1/27Linux OS Analysis系统调用处理程序也和其他异常处理程序的结构类似在进程的内核态堆栈中保存大多数寄存器的内容(即保存保存恢复进程到用户态执行所需要的上下文上下文)调用调用相应的系统调用服务例程系统调用服务例程处理系统调用sys_xxx通过ret_from_sys_call()从系统调用返回返回2023/1/28Linux OS Analysis应用程序、封装例程、系统调用处理程序及系统调用服

5、务例程之间的关系应用程序、封装例程、系统调用处理程序及系统调用服务例程之间的关系syscall_exit:2023/1/29Linux OS Analysis为了把系统调用号与相应的服务例程关联起来,内核利用了一个系统调用分派表(dispatch table)。这个表存放在sys_call_table数组中,有若干个表项(2.6.26中,是356):第n个表项对应了系统调用号为n的服务例程的入口地址的指针观察sys_call_table(syscall_table_32.S以及entry_32.S最后)2023/1/210Linux OS Analysis关于系统调用表的大小关于系统调用表的大

6、小2023/1/211Linux OS Analysis初始化系统调用初始化系统调用内核初始化期间调用trap_init()函数建立IDT表中向量128对应的表项,语句如下:讀 该调用把下列值存入这个系统门描述符的相应字段:segment selector内核代码段_KERNEL_CS的段选择符offset指向system_call()异常处理程序的入口地址type置为15。表示这个异常是一个陷阱,相应的处理程序不禁止可屏蔽中断DPL(描述符特权级)置为3。这就允许用户态进程访问这个门,即在用户程序中使用int$0 x80是合法的2023/1/212Linux OS Analysissyste

7、m_call()函数函数参见entry_32.S2023/1/213Linux OS Analysis参数传递参数传递系统调用也需要输入输出参数,例如实际的值用户态进程地址空间的变量的地址甚至是包含指向用户态函数的指针的数据结构的地址system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即由eax传递的系统调用号一个应用程序调用fork()封装例程,那么在执行int$0 x80之前就把eax寄存器的值置为2(即_NR_fork)。这个寄存器的设置是libc库中的封装例程进行的,因此用户一般不关心系统调用号进入sys_call之后,立即将eax的值压入内核堆栈对对

8、C库进行反汇编,察看库进行反汇编,察看int$0 x802023/1/214Linux OS Analysis很多系统调用需要不止一个参数普通C函数的参数传递是通过把参数值写入堆栈(用户态堆栈或内核态堆栈)来实现的。但因为系统调用是一种特殊函数,它由用户态进入了内核态,所以既不能使用用户态的堆栈也不能直接使用内核态堆栈用户态堆栈用户态C函数内核态堆栈内核态C函数2023/1/215Linux OS Analysis在int$0 x80汇编指令之前,系统调用的参数被写入CPU的寄存器。然后,在进入内核态调用系统调用服务例程之前,内核再把存放在CPU寄存器中的参数拷贝到内核态堆栈中。因为毕竟服务例

9、程是C函数,它还是要到堆栈中去寻找参数的用户态堆栈用户态C函数内核态堆栈内核态C函数寄存器SAVE_ALL2023/1/216Linux OS Analysis回想一下在进入中断和异常处理程序前,在内核态堆栈中保存的pt_regs结构,此时pt_regs结构中的一些寄存器被用来传递参数或者pt_regs结构本身就是参数2023/1/217Linux OS Analysis参数传递举例参数传递举例处理write系统调用的sys_write服务例程声明如下该函数期望在栈顶找到fd,buf和count参数 在封装sys_write()的封装例程中,将会在ebx、ecx和edx寄存器中分别填入这些参数

10、的值,然后在进入system_call时,SAVE_ALL会把这些寄存器保存在堆栈中,进入sys_write服务例程后,就可以在相应的位置找到这些参数asmlinkage使得编译器不通过寄存器(x=0)而使用堆栈传递参数参见参见SAVE_ALL2023/1/218Linux OS Analysis197897 000bed90:197898 bed90:65 83 3d 0c 00 00 00 cmpl$0 x0,%gs:0 xc197899 bed97:00197900 bed98:75 1d jne bedb7 197901 bed9a:53 push%ebx197902 bed9b:8b

11、 54 24 10 mov 0 x10(%esp),%edx197903 bed9f:8b 4c 24 0c mov 0 xc(%esp),%ecx197904 beda3:8b 5c 24 08 mov 0 x8(%esp),%ebx197905 beda7:b8 04 00 00 00 mov$0 x4,%eax197906 bedac:cd 80 int$0 x80197907 bedae:5b pop%ebx197908 bedaf:3d 01 f0 ff ff cmp$0 xfffff001,%eax197909 bedb4:73 2d jae bede3 197910 bedb6:

12、c3 ret2023/1/219Linux OS Analysis由此,使用寄存器传递参数具有如下限制:1)每个参数的长度不能超过寄存器的长度,即32位2)在系统调用号(eax)之外,参数的个数不能超过6个(ebx,ecx,edx,esi,edi,ebp)?超过6个怎么办?2023/1/220Linux OS Analysis传递返回值传递返回值服务例程的返回值是将会被写入eax寄存器中 这个是在执行“return”指令时,由编译器自动完成的2023/1/221Linux OS Analysis验证参数验证参数在内核打算满足用户的请求之前,必须仔细的检查所有的系统调用参数 比如前面的write

13、()系统调用,fd参数是一个文件描述符,sys_write()必须检查这个fd是否确实是以前已打开文件的一个文件描述符,进程是否有向fd指向的文件的写权限,如果有条件不成立,那这个处理程序必须返回一个负数2023/1/222Linux OS Analysis只要一个参数指定的是地址,那么内核必须检查它是否在这个进程的地址空间之内,有两种验证方法:验证这个线性地址是否属于进程的地址空间仅仅验证这个线性地址小于PAGE_OFFSET对于第一种方法:费时大多数情况下,不必要对于第二种方法:高效可以在后续的执行过程中,很自然的捕获到出错的情况从linux2.2开始执行第二种检查2023/1/223Li

14、nux OS Analysis对用户地址参数的粗略验证对用户地址参数的粗略验证在内核中,可以访问到所有的内存要防止用户将一个内核地址作为参数传递给内核,这将导致它借用内核代码来读写任意内存2023/1/224Linux OS Analysis2023/1/225Linux OS Analysis检查方法:最高地址:addr+size-11、是否超出3G边界2、是否超出当前进程的地址边界对于用户进程:不大于3G对于内核线程:可以使用整个4G2023/1/226Linux OS Analysis访问进程的地址空间访问进程的地址空间系统调用服务例程需要非常频繁的读写进程地址空间的数据2023/1/2

15、27Linux OS Analysis访问进程地址空间时的缺页访问进程地址空间时的缺页内核对进程传递的地址参数只进行粗略的检查访问进程地址空间时的缺页,可以有多种情况合理的缺页:来自虚存技术页框不存在或者写时复制由于错误引起的缺页由于非法引起的缺页2023/1/228Linux OS Analysis非法缺页的判定非法缺页的判定内核中,只有少数几个函数/宏会访问用户地址空间对于一次非法缺页,一定来自于这些函数/宏可以将访问用户地址空间的指令的地址一一列举出来,当发生非法缺页时,根据引起出错的指令地址来定位Linux使用了异常表的概念_ex_table,_start_ex_table,_stop

16、_ex_table2023/1/229Linux OS Analysis_ex_table的表项哪条指令访问了用户地址空间如果这条指令引起了非法缺页,该怎么处理Fixup所指向的代码,称为修正代码通常为汇编代码2023/1/230Linux OS Analysisfixup_exception2023/1/231Linux OS Analysis缺页异常对非法缺页的处理缺页异常对非法缺页的处理在缺页异常do_page_fault中,若最后发现是非法缺页,就会执行下面的操作假设找到了修正代码,会发生什么事情?该操作使用引起出错的代码地址在异常表中进行查找,若找到,就返回相应的修正代码地址,填写在

17、regs-eip中2023/1/232Linux OS AnalysisIDT表,进入异常处理某内核函数缺页缺页处理作为一次故障,要重新执行引起出错的代码正常情况下,这个eip在发生异常时,由硬件保存到堆栈中因此,正常情况下,返回此处非法异常修改堆栈中的eip,指向修正代码因此,非法缺页时,返回此处修正代码异常处理后,返回eip指定的位置执行2023/1/233Linux OS Analysis异常表的生成和修正代码异常表的生成和修正代码2023/1/234Linux OS Analysis举例举例2023/1/235Linux OS Analysis系统调用的返回系统调用的返回参见中断中的返回2023/1/236Linux OS Analysis中断、异常、系统调用小结中断、异常、系统调用小结用户态内核态IDT表中断异常系统调用iretret_from_forkret_from_exceptionret_from_intrsyscall_exit2023/1/237Linux OS AnalysisProject参见课程主页2023/1/238Linux OS Analysis

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁