




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Chapter5:系统调用
■为什么需要系统调用
■相关数据和代码
■例:系统调用wetuidO的实现
■添加一个系统调用mysyscall
■再实现一个稍复杂的系统调用
边干边学——Linux内核指导
为什么需要系统调用(1)
边干边学——Linux内核指导
为什么需要系统调用(2)
用户空间而、内核空间
5模=式^切换、
sys_foo...
厂模式切换、
©边干边学——Linux内核指导
相关数据和代码
■arch/i386/kemel/traps.c
■•
■arch/i386/kernel/entry.S
系统调用时的内核栈
syscalltable
systemcall和retfix)msyscall
■include/linux/unistd.h
系统调用编号
宏定义展开系统调用
glibC展开系统调用INLINE_SYSCALL(getuid,0);
©边干边学——内核指导
Linux
边干边学——Linux内核指导
系统调用时的内核栈
18*Stacklayoutin'ret_from_system_caH':
19*ptraceneedstohaveallregsonthestack.
20*iftheorderhereischanged,itneedstobe
21*updatedinfbrk.c:copy_process,signal.crdosignal,
*ptrace.candptrace.h
23*
24*0(%esp)-%ebx
N-*4(%esp)-%ecx
26*8(%esp)-%edx
27*C(%esp)-%esi
28*10(%esp)-%edi
29*14(%esp)-%ebp
JU*18(%esp)-%eax
31*lC(%esp)-%ds
32*20(%esp)-%es
33*24(%esp)-orig_eax
34*28(%esp)-%eip
35*2C(%esp)-%cs
36*30(%esp)-%eflags
37*34(%esp)-%oldesp
38*38(%esp)-%oldss
39*
40*"current"isinregister%ebxduringanyslowentries.
边干边学---Linux内核指导
系统调用时的内核栈
#defineSAVEALL\
.cld;\
pushl%es;\
pushl%ds;\
pushl%eax;\
pushl%ebp;\
pushl%edi;\
pushl%esi;\
pushl%edx;\
pushl%ecx;\
pushl%ebx;\
movl$(_KERNEL_DS),%edx;\
movl%edx,%ds;\
movl%edx,%es;
边干边学——Linux内核指导
系统调用时的内核栈
ftdefineRESTORE_ALL\
popl%ebx;\
popl%ecx;\
popl%edx;\
popl%esi;\
popl%edi;\
popl%ebp;\
popl%eax;\
1:popl%ds;\
2:popl%es;\
addl$4,%esp;\
3:iret;\
©边干边学——Linux内核指导
syscalltable
ENTRY(sys_call_table)
.longSYMBOL_NAME(sys_ni_syscall)
.longSYMBOLNAME(sysexit)
,longSYMBOL_NAME(sys_fdrk)
102.longSYMBOLNAME(sysread)
.longSYMBOLNAME(syswrite)
.longSYMBOLNAME(sysopen)/*5*/
.longSYMBOL_NAME(sys_ni_syscall)/*reservedforIremovexattr*/
.longSYMBOL_NAME(sys_ni_syscall)/*reservedforfremovexattr*/
637
.reptNR_syscalls-(.-sys_call_table)/4
,longSYMBOL_NAME(sys_ni_syscall)
.endr
边干边学——Linux内核指导
syscalltable
eax*4ENTRY(sys_call_table)
,longSYMBOL_NAME(sys_ni_...)
JongSYMBOL_NAME(sys_exit)
,longSYMBOL二NAME(sys二fork)
JongSYMBOL_NAME(sys_read)
,longSYMBOL_NAME(sys_write)
JongSYMBOL_NAME(sys_open)
▼
syscalltable首地址卜---►QA.longSYMBOL_NAME(sys_getuid)
边干边学——Linux内核指导
systemcall
ENTRY(systemcall)#int0x80后执行
pushl%eax#saveorigeax
196'SAVEALL
GET_CURRENT(%ebx)
testb$0x02,tsk_ptrace(%ebx)#PTTRACESYS
jnetracesys
cmpl$(NR_syscalls),%eax
jaebadsys
call*SYMBOL_NAME(sys_call_table)(,%eax,4)
movl%eax,EAX(%esp)#savethereturnvalue
20ENTRY(ret_from_sys_call)
205cli
边干边学——Linux内核指导
ret_from_sys_call
ENTRY(retfromsyscall)
cli#need_reschedandsignalsatomictest
cmpl$O,need_resched(%ebx)
jnereschedule
cmpl$O,sigpending(%ebx)
jnesignalretum
restoreall:
RESTOREALL
边干边学——Linux内核指导
用户空间内核空间内核堆栈中的变化注解
压入用户ss
由于是陷入进来
压入用户esp
内核的,所以机
压入EFLAGS器自动保存与转
压入cs换堆栈。
压入eip
压入eax
push
push%es;
push%ds;
push%eax;
push%ebp;
push%edi;
push%esi;
push%edx;
push%ecx;
%ebx
popl%ebx;
popl%ecx;
RESTORE_ALLpopl%edx;
popl%esi;
popl%edi;
popl%ebp;
popl%eax;
popl%ds;
popl%es;
addl$4,%esp—等价于弹出eax
iret
弹出eip
弹出cs
J
回到用户空间>弹出EFLAGS
弹出用户esp
弹出用户ss
边干边学——Linux内核指导
arch/i386/kernel/traps.c
voidinittrapinit(void)〃初始化中断描述符表IDT
settrapgate(0,÷_error);
set_trap_gate(l,&debug);
setintrgate(2,&nmi);
set_system_gate(3,&int3);
set_trap_gate(l9,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
r边干边学——Linux内核指导
系统调用编号
include/asm-i386/unistd.h
#defineNRexit1
#defineNRfork2
#defineNRread3
#defineNRwrite4
#defineNRopen5
#defineNRclose6
#defineNRllistxattr233
#defineNRflistxattr234
#defineNRremovexattr235
#defineNRlremovexattr236
#defineNRfremovexattr237
边干边学——Linux内核指导
宏定义展开系统调用
#define_syscall3(type,name,typel,argl,type2,arg2,type3,arg3)\
typename(typelargl,type2arg2,type3arg3)\
{\
long_res;\
asm_volatile(nint$0x80"\
:res)\
:"0"(_NR_##name),nbn((long)(argl)),McH((long)(arg2)),\
((long)(arg3)));\
_syscall_return(type9_res);\
边干边学——Linux内核指导
宏定义展开系统调用
movl$_NR_##name,%eax〃先为输入参数分配寄存器
■•
movlarg1,%ebx
movlarg25%ecx
movlarg3,%edx
#APP
int$0x80〃汇编代码
#NO_APP
movl%eax,res//最后处理输出参数
©边干边学——Linux内核指导
■一个简单的程序,但包含系统调用和库函数调用
■"
#include<linux/unistd.h>
/*allsystemcallsneedthisheader*/
intmain(){
inti=getuid();
printf(uHelloWorld!Thisismyuid:%d\n\i);
■假定vunistd.h>定义了“宏”
_syscallO(int,getuid);
边干边学——Linux内核指导
■这个“宏”被getuid()展开后
intgetuid(void)
long_res;
asm_volatile("int$0x80”
:“=a"(_res)#输出
_NR_getuid));#输入
_syscall_return(int9_res);
}一—一
■显然,NRgetuid(24)放入eax,并int0x80
边干边学——Linux内核指导
||幺例:系统调用getuidO的实现
•»
■因为系统初始化时设定了
set_system_gate(SYSCALL_VECTOR,&system_call);
■所以进入system_call
ENTRY(systemcall)
pushl%eax#saveorigeax
SAVEALL
GET_CURRENT(%ebx)
testb$0x02,tsk_ptrace(%ebx)#PTTRACESYS
jnetracesys
cmpl$(NR_syscalls),%eax
jaebadsys
call*SYMBOL_NAME(sys_call_table)(,%eax,4)
movl%eax,EAX(%esp)
边干边学——Linux内核指导
■注意第202行,止匕时eax为24
■查sys_call_table,得到call指令的操作数
sys_getuidl6
■调用函数sys_getuidl6()
longsys_getuidl6(void)
146{
returnhigh21owuid(current->uid);
148)
边干边学——Linux内核指导
例:系统调用getuidO的实现
•»
■第202行完成后,接着执行第203行后面的指令
movl%eax,EAX(%esp)
204ENTRY(retfromsyscall)
205cli
cmpl$O9need_resched(%ebx)
jnereschedule
cmpl$O?sigpending(%ebx)
jnesignalretum
restore_all:
RESTOREALL
边干边学——Linux内核指导
乂例:系统调用getuidO的实现
■第203行:返回值从eax移到堆栈中eax的位置
■假设没有什么意外发生,于是ret—ftom_SyS_Call直
接到RESTORE_ALL,从堆栈里面弹由一保存的寄
存器,堆栈切质(iret)
■进程回到用户态,返回值保存在eax中
■print甘丁印出
HelloWorld!Thisismyuid:551
边干边学——Linux内核指导
边干边学——Linux内核指导
■系统调用的编号名字—NRmysyscall
■改写/usr/include/asm/unistd.h
240#defineNRllistxattr233
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025企业办公场地的租赁合同
- 2025资金信托合同模板
- 辅导班合同协议书样本
- 礼盒供货合同协议书怎么写
- 情感咨询服务合同协议书
- 签租房合同协议书流程
- 铸铁加工合同协议书模板
- 2025物流仓储合同标准格式模板
- 入股做生意合同协议书
- 出租公司解聘合同协议书
- 《空中领航》全套教学课件
- 人教版五年级下册数学操作题期末专项练习(及解析)
- 中药熏洗法操作评分标准与流程
- 学习解读《执业兽医和乡村兽医管理办法》课件
- 室内装饰不锈钢技术交底
- 1.3.1动量守恒定律课件(共13张PPT)
- 白黑白装饰画欣赏黑白装饰画的特点黑白装饰画的表现形式黑白装饰 bb
- TCECS 850-2021 住宅厨房空气污染控制通风设计标准
- 调度指挥与统计分析课程教学设计
- GB∕T 25119-2021 轨道交通 机车车辆电子装置
- 支气管分段亚段及及支气管镜检查
评论
0/150
提交评论