文档介绍:Chapter 5: 系统调用
为什么需要系统调用
相关数据和代码
例:系统调用getuid()的实现
添加一个系统调用mysyscall
再实现一个稍复杂的系统调用
为什么需要系统调用(1)
边干边学——Linux内核指导
为什么需要系统调用(2)
边干边学——Linux内核指导
相关数据和代码
arch/i386/kernel/
arch/i386/kernel/
系统调用时的内核栈
sys_call_table
system_call和ret_from_sys_call
include/linux/
系统调用编号
宏定义展开系统调用
glibc展开系统调用INLINE_SYSCALL (getuid, 0);
边干边学——Linux内核指导
系统调用时的内核栈
陷入内核时,系统自动从当前进程的TSS(任务状态段)中获得内核栈的SS和ESP,并完成栈切换
边干边学——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 :copy_process, :do_signal,
22 * and
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.
边干边学——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;
边干边学——Linux内核指导
系统调用时的内核栈
#define RESTORE_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内核指导
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 SY