系统调用的工作机制
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl
一、前情提要
系统调用 | 操作系统为用户态进程与硬件设备进行交互提供了一组接口 |
---|---|
API | 应用编程接口,是一个函数定义。 |
系统调用通过软中断向内核发出明确的请求。(eg:sysenter)
操作系统提供API和系统调用的关系 Libc库定义的一些API引用封装例程(wrapper routine). 一般每个系统调用对应一个封装例程。 库再用这些封装例程定义给用户的API. 不是每个API对应一个特定系统调用 返回值:1.大部分封装例程返回一个整数,值含义依赖于相应的系统调用; 2.-1,多数情况——内核不满足进程请求。 3.Libc定义errno变量包含特定出错码
二、两种方式调用系统调用的工作过程
用户态进程——(调用)——>系统调用 CPU——(切换)———内态核执行一个内核函数 linux中,通过执行int $0x80执行系统调用的,此汇编指令产生向量为128的编程异常。 中断向量0x80与system_call绑定起来 系统调用号将xyz和sys_xyz关联起来了。 系统调用三层皮 API XYZ,中断向量system_call,中断服务程序sys_xyz
system_call:Linux所有系统调用的入口点。
传参: 1.内核实现不同系统调用 2.进程必须指明哪个系统调用,这需要传递一个名为系统调用号的参数。使用EAX寄存器传递 3.ebx,ecx,edx,esi,edi按照顺序存放前五个参数。 4.需要六个或六个以上参数时,应用一个单独的寄存器存放指向所有参数在用户空间地址的指针。 5.返回值用eax
寄存器传递参数限制 1.参数长度小于或等于寄存器长度(32位); 2.除系统调用号(EAX),参数个数不超6个( EBX,ECX,EDX,ESI,EDI,EBP) 进入内核态后,可访问所有地址空间,通过用户块内存传递数据 下面使用的是getpid的系统调用,查表得 则系统调用号是20
1.库函数调用系统调用的工作过程
getpid()函数功能:取得进程识别码,返回值是进程的ID 这里直接使用getpid库函数进行系统调用。 传入的参数为NULL,通过EAX传入,再通过EAX将返回值传回。
2.汇编代码调用系统调用的工作过程
系统调用传递第一个参数ebx,这里是null 8行,将ebx清零; 9行,将20放入EAX 11行,返回值用EAX存储 总之,int 80触发中断,找到中断向量表,从表中寻找中断向量(或中断门),通过中断向量,找到系统调用表,找到system_call JMP EAX*4+system_table
3.两种方式的编译运行结果分别是2999和3065.
(-14是实验出现了错误,使用了错误的系统调用号)
4.总结部分
需要阐明自己对“系统调用的工作机制”的理解。
应用程序应该以某种方式(库函数或汇编代码)通知系统 告诉内核自己需要执行一个系统调用,希望系统切换到内核态。 内核就可以代表应用程序在内核空间执行系统调用。 通知内核的机制是靠软中断实现的: 通过引发异常将系统切换内核态执行异常处理程序(系统调用处理程序)。
注明“郑伟 + 参考书《内核分析与实现》 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
时间: 2024-10-07 04:59:34