为了正常的体验网站,请在浏览器设置里面开启Javascript功能!
首页 > Linux系统调用

Linux系统调用

2012-08-14 29页 ppt 437KB 14阅读

用户头像

is_884634

暂无简介

举报
Linux系统调用nullLinux系统调用Linux系统调用为什么需要系统调用 相关数据和代码 例:系统调用getuid()的实现 添加一个系统调用mysyscall 再实现一个稍复杂的系统调用 为什么需要系统调用(1)为什么需要系统调用(1)为什么需要系统调用(2)为什么需要系统调用(2)相关数据和代码相关数据和代码arch/i386/kernel/traps.c 异常处理 arch/i386/kernel/entry.S 系统调用时的内核栈 sys_call_table system_call和ret_fr...
Linux系统调用
nullLinux系统调用Linux系统调用为什么需要系统调用 相关数据和代码 例:系统调用getuid()的实现 添加一个系统调用mysyscall 再实现一个稍复杂的系统调用 为什么需要系统调用(1)为什么需要系统调用(1)为什么需要系统调用(2)为什么需要系统调用(2)相关数据和代码相关数据和代码arch/i386/kernel/traps.c 异常处理 arch/i386/kernel/entry.S 系统调用时的内核栈 sys_call_table system_call和ret_from_sys_call include/linux/unistd.h 系统调用编号 宏定义展开系统调用 glibc展开系统调用INLINE_SYSCALL (getuid, 0); 系统调用时的内核栈系统调用时的内核栈陷入内核时,系统自动从当前进程的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 * 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; \ 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 \ 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; \ sys_call_tablesys_call_table398 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_tablesys_call_tablesystem_callsystem_call194 ENTRY(system_call) # int 0x80后执行 195 pushl %eax # save orig_eax 196 SAVE_ALL 197 GET_CURRENT(%ebx) 198 testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS 199 jne tracesys 200 cmpl $(NR_syscalls),%eax 201 jae badsys 202 call *SYMBOL_NAME(sys_call_table)(,%eax,4) 203 movl %eax,EAX(%esp) # save the return value 204 ENTRY(ret_from_sys_call) 205 cliret_from_sys_callret_from_sys_callENTRY(ret_from_sys_call) cli # need_resched and signals atomic test cmpl $0,need_resched(%ebx) jne reschedule cmpl $0,sigpending(%ebx) jne signal_return restore_all: RESTORE_ALL nullarch/i386/kernel/traps.carch/i386/kernel/traps.c916 void __init trap_init(void) //初始化中断描述符表IDT { …… 923 set_trap_gate(0,÷_error); 924 set_trap_gate(1,&debug); 925 set_intr_gate(2,&nmi); 926 set_system_gate(3,&int3); …… 942 set_trap_gate(19,&simd_coprocessor_error); 944 set_system_gate(SYSCALL_VECTOR,&system_call); 系统调用编号系统调用编号include/asm-i386/unistd.h 8 #define __NR_exit 1 9 #define __NR_fork 2 10 #define _NR_read 3 11 #define NR_write 4 12 #define NR_open 5 13 #define NR_close 6 …… 240 #define __NR_llistxattr 233 241 #define __NR_flistxattr 234 242 #define __NR_removexattr 235 243 #define __NR_lremovexattr 236 244 #define __NR_fremovexattr 237宏定义展开系统调用宏定义展开系统调用#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ "d" ((long)(arg3))); \ __syscall_return(type,__res); \ } 宏定义展开系统调用宏定义展开系统调用movl $__NR_##name, %eax //先为输入参数分配寄存器 movl arg1, %ebx movl arg2, %ecx movl arg3, %edx #APP int $0x80 //汇编代码 #NO_APP movl %eax, __res //最后处理输出参数 例:系统调用getuid()的实现例:系统调用getuid()的实现一个简单的程序,但包含系统调用和库函数调用 #include /* all system calls need this header */ int main(){ int i = getuid(); printf(“Hello World! This is my uid: %d\n”, i); } 假定定义了“宏” _syscall0( int, getuid); 例:系统调用getuid()的实现例:系统调用getuid()的实现这个“宏”被getuid()展开后 int getuid(void) { long __res; __asm__ volatile ("int $0x80" : “=a” (__res) #输出 : “0” (__NR_getuid)); #输入 __syscall_return(int,__res); } 显然,__NR_getuid(24)放入eax,并int 0x80例:系统调用getuid()的实现例:系统调用getuid()的实现因为系统初始化时设定了 set_system_gate(SYSCALL_VECTOR,&system_call); 所以进入system_call 194 ENTRY(system_call) 195 pushl %eax # save orig_eax 196 SAVE_ALL 197 GET_CURRENT(%ebx) 198 testb $0x02,tsk_ptrace(%ebx) # PT_TRACESYS 199 jne tracesys 200 cmpl $(NR_syscalls),%eax 201 jae badsys 202 call *SYMBOL_NAME(sys_call_table)(,%eax,4) 203 movl %eax,EAX(%esp) 例:系统调用getuid()的实现例:系统调用getuid()的实现注意第202行,此时eax为24 查sys_call_table,得到call指令的操作数sys_getuid16 调用函数sys_getuid16() 145 asmlinkage long sys_getuid16(void) 146 { 147 return high2lowuid(current->uid); 148 } 例:系统调用getuid()的实现例:系统调用getuid()的实现第202行完成后,接着执行第203行后面的指令 203 movl %eax,EAX(%esp) 204 ENTRY(ret_from_sys_call) 205 cli 206 cmpl $0,need_resched(%ebx) 207 jne reschedule 208 cmpl $0,sigpending(%ebx) 209 jne signal_return 210 restore_all: 211 RESTORE_ALL例:系统调用getuid()的实现例:系统调用getuid()的实现第203行:返回值从eax移到堆栈中eax的位置 假设没有什么意外发生,于是ret_from_sys_call直接到RESTORE_ALL,从堆栈里面弹出保存的寄存器,堆栈切换(iret) 进程回到用户态,返回值保存在eax中 printf打印出 Hello World! This is my uid:551添加一个系统调用mysyscall添加一个系统调用mysyscall功能要求 调用这个mysyscall ,使用户的uid等于0 添加一个系统调用mysyscall添加一个系统调用mysyscall系统调用的编号名字 __NR_mysyscall 改写/usr/include/asm/unistd.h 240 #define __NR_llistxattr 233 241 #define __NR_flistxattr 234 242 #define __NR_removexattr 235 243 #define __NR_lremovexattr 236 244 #define __NR_fremovexattr 237 245 #define __NR_mysyscall 238添加一个系统调用mysyscall添加一个系统调用mysyscall内核中实现该系统调用的程序的名字 sys_mysyscall 改写arch/i386/kernel/entry.S 398 ENTRY(sys_call_table) 399 .long SYMBOL_NAME(sys_ni_syscall) …… 636 .long SYMBOL_NAME(sys_ni_syscall) 637 .long SYMBOL_NAME(sys_mysyscall) 638 639 .rept NR_syscalls-(.-sys_call_table)/4 640 .long SYMBOL_NAME(sys_ni_syscall) 641 .endr 添加一个系统调用mysyscall添加一个系统调用mysyscall把一小段程序添加在kernel/sys.c asmlinkage int sys_mysyscall(void) { current->uid = current->euid = current->suid = current->fsuid = 0; return 0; } 记得重新编译内核,启动新内核添加一个系统调用mysyscall添加一个系统调用mysyscall编写一段测试程序检验实验结果 #include _syscall0(int,mysyscall) /* 注意这里没有分号 */ /*int mysyscall(void) { long __res; __asm__ volatile ("int $0x80" : “=a” (__res) #输出 : “” (__NR_mysyscall)); #输入 __syscall_return(int,__res); } */ int main() { mysyscall(); printf(“em…, this is my uid: %d. \n”, getuid()); } 一个稍复杂的系统调用一个稍复杂的系统调用用到了module 5-6-3.c:sys_pedagogictime(struct timeval *tv) 5-6-4.c:测试pedagogictime
/
本文档为【Linux系统调用】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索