Chapter5:系统调用 ■为什么需要系统调用 ■相关数据和代码 ■例:系统调用 getuid(的实现 ■添加一个系统调用 mysyscall 再实现一个稍复杂的系统调用 边干边学— Linux内核指导
边干边学——Linux内核指导 Chapter 5: 系统调用 n 为什么需要系统调用 n 相关数据和代码 n 例:系统调用getuid()的实现 n 添加一个系统调用mysyscall n 再实现一个稍复杂的系统调用
为什么需要系统调用(1) 用户程序调用内核提供的功能 公共系统调用接口 POSIX.1 具体的系统实现 Kerne 边干边学— Linux内核指导
边干边学——Linux内核指导 为什么需要系统调用(1)
为什么需要系统调用(2) 用户空间 模式切换 内核空间 sys_ foo. 模式切换 边干边学— Linux内核指导
边干边学——Linux内核指导 为什么需要系统调用(2)
相关数据和代码 arch/1386/kernel/traps. c arch/1386/kernel/entry. S 系统调用时的内核栈 sys call table system call /ret from sys call include/linux/unistd. h 系统调用编号 宏定义展开系统调用 glibc展开系统调用 INLINE SYSCALL( ( getuid,0) 边干边学— Linux内核指导
边干边学——Linux内核指导 相关数据和代码 n arch/i386/kernel/traps.c n arch/i386/kernel/entry.S 系统调用时的内核栈 sys_call_table system_call和ret_from_sys_call n include/linux/unistd.h 系统调用编号 宏定义展开系统调用 glibc展开系统调用INLINE_SYSCALL (getuid, 0);
系统调用时的内核栈 内核栈 用户栈 向内中断 向外返回 用户空间ss 「函数返回地址 用户空间esp EfLAGS 局部变量 用户空间cs 中断前及iret 用户空间ei 可用空间 (系统调用返回)后 的esp 系统调用号 用户ss 中断后( SAVE ALL前) 及iret前 ( RESTORE ALL后)的 可用空间 陷入内核时,系统自动从当前进程的TSS(任 务状态段)中获得内核栈的SS和ESP,并完 task struct 成栈切换 内核ss 边干边学— Linux内核指导
边干边学——Linux内核指导 系统调用时的内核栈 用户空间ss 用户空间esp EFLAGS 用户空间cs 用户空间eip 系统调用号 可用空间 可用空间 eip 函数返回地址 局部变量 内核栈 用户栈 中断后(SAVE_ALL前) 及iret前 (RESTORE_ALL后)的 esp 内核ss 向外返回 向内中断 中断前及iret (系统调用返回)后 的esp 用户ss task_struct 陷入内核时,系统自动从当前进程的TSS(任 务状态段)中获得内核栈的SS和ESP,并完 成栈切换
系统调用时的内核栈 18* Stack layout in'ret from system call 19* ptrace needs to have all regs on the stack 20* if the order here is changed. it needs to be 21* updated in fork. c copy process, signal. c: do signal 22* ptrace.c and ptrace. h 23 25 8(%esp)-%edx C(%esp)-%esi 28*10(%esp)-%edi 29*14(%esp)-%eb 30*18(%esp)-%eax 31*1C(%esp)-%ds 33* 24(%esp)-orig_eax 34*28(%sp)-%eip 35*2C(%oesp)-%c 36* 30(%esp)-%eflags 37 34(%esp)-%oldest 38* 38(%esp)-%oldss 40*"current"is in register %ebx during any slow entries 边干边学— Linux内核指导
边干边学——Linux内核指导 系统调用时的内核栈 18 * Stack layout in 'ret_from_system_call': 19 * ptrace needs to have all regs on the stack. 20 * if the order here is changed, it needs to be 21 * updated in fork.c:copy_process, signal.c:do_signal, 22 * ptrace.c and ptrace.h 23 * 24 * 0(%esp) - %ebx 25 * 4(%esp) - %ecx 26 * 8(%esp) - %edx 27 * C(%esp) - %esi 28 * 10(%esp) - %edi 29 * 14(%esp) - %ebp 30 * 18(%esp) - %eax 31 * 1C(%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" is in register %ebx during any slow entries
系统调用时的内核栈 #define save all cld pushl %es; I pushl%ds; pushl %eax; V pushl %ebp pushl %edi pushl %esi; I pushl %edx push1 o ocx pushl %ebx; V movl S( KERNEL DS), %edx; I movl %edx %ds: moⅥoedx,es; 边干边学— Linux内核指导
边干边学——Linux内核指导 系统调用时的内核栈 #define SAVE_ALL \ 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;
系统调用时的内核栈 #define reStore all O b pppppp O O O ppppp 11111 %%%%%% cdsdb xXxiip O p o pl %e a X po pl %d s popl %es add1 $4, %es p 1r e t 边干边学— Linux内核指导
边干边学——Linux内核指导 系统调用时的内核栈 # d e f i n e R E S T O R E _ A L L \ p o p l % e b x ; \ p o p l % e c x ; \ p o p l % e d x ; \ p o p l % e s i ; \ p o p l % e d i ; \ p o p l % e b p ; \ p o p l % e a x ; \ 1 : p o p l % d s ; \ 2 : p o p l % e s ; \ a d d l $ 4 , % e s p ; \ 3 : i r e t ; \
sys call table 398 ENTRY(Sys call table) 399 long SYMBOL NAME(Sys ni syscall) 400 long SYMBOL NAME(sys exit) 401,long SYMBOL NAME(sys fork) 402 long SYMBOL NAME(Sys read) long SYMBOL NAME(Sys write) 404. long SYMBOL NAME(Sys open) 635 long SYMBOL NAME(Sys ni syscall) /*reserved for lremovexattr*/ 636. long SYMBOL NAME(Sys ni syscall)/reserved for fremovexattr * 637 638 rept NR syscalls-(-sys call table)/4 639 long SYMBOL NAME(sys ni syscall) 04 边干边学— Linux内核指导
边干边学——Linux内核指导 sys_call_table 398 ENTRY(sys_call_table) 399 .long SYMBOL_NAME(sys_ni_syscall) 400 .long SYMBOL_NAME(sys_exit) 401 .long SYMBOL_NAME(sys_fork) 402 .long SYMBOL_NAME(sys_read) 403 .long SYMBOL_NAME(sys_write) 404 .long SYMBOL_NAME(sys_open) /* 5 */ … 635 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for lremovexattr */ 636 .long SYMBOL_NAME(sys_ni_syscall) /* reserved for fremovexattr */ 637 638 .rept NR_syscalls-(.-sys_call_table)/4 639 .long SYMBOL_NAME(sys_ni_syscall) 640 .endr
sys call table eax* 4 ENTRY(sys call table) long SYMBOL_NAME(sys_ni_.) long SYMBOL_NAME(sys_exit long SYMBOL_NAME(sys_fork long SYMBOL_NAME(sys_read) long SYMBOL_NAME(sys_write) long SYMBOL NAME(sys_open ·· ssca‖tabe首地址→| long SYMBOL_NAME( sys_ getuid) 边干边学— Linux内核指导
边干边学——Linux内核指导 sys_call_table