LINUX系统调用课件_第1页
LINUX系统调用课件_第2页
LINUX系统调用课件_第3页
LINUX系统调用课件_第4页
LINUX系统调用课件_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

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

文档简介

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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论