随笔:操作系统:系统调用的实现
2017-05-27 17:24
260 查看
1.用户态与内核态:
*将内核程序与用户程序隔离!
内核态能访问任何数据,用户态不能访问内核数据。
当前程序执行在什么态?因CS:IP是当前指令,故用CS的最低两位来表示:0是内核态(00),3是用户态(11)
2.中断指令:int
Intel x86中,中断指令:int
将使CS中的CPL改为0,进入内核。这是用户程序(CPL=3,DPL=0)发起的调用内核代码的唯一方式
*系统调用:
(1)用户程序中包含一段包含int指令的代码
(2)操作系统写中断处理,获取想调程序的编号
(3)操作系统根据编号执行相应代码
过程:
linux/lib/write.c
*将内核程序与用户程序隔离!
内核态能访问任何数据,用户态不能访问内核数据。
当前程序执行在什么态?因CS:IP是当前指令,故用CS的最低两位来表示:0是内核态(00),3是用户态(11)
2.中断指令:int
Intel x86中,中断指令:int
将使CS中的CPL改为0,进入内核。这是用户程序(CPL=3,DPL=0)发起的调用内核代码的唯一方式
*系统调用:
(1)用户程序中包含一段包含int指令的代码
(2)操作系统写中断处理,获取想调程序的编号
(3)操作系统根据编号执行相应代码
过程:
应用程序: 调用printf(xxx) c函数库: 库函数printf(xxx) 库函数write(xxx) os内核: 系统调用write(xxx)
linux/lib/write.c
#include <unistd.h> _syscall3(int, write, int, fd, const char *buf, off_t, count)linux/include/unistd.h
define _syscall3(type, name, atype, a ,btype, b, ctype, c) type name(atype a ,btype b, ctype c) { long_res; __asm__ volatile("int 0x80":"=a(__res)":""(__NR__##name),"b"((long)(a)),"c"((long)(b)),"d"((long)(c))); if(__res>=0) return (type)__res; errno =-__res; return -1; }
#define __NR_write 4 /* __NR_write 是系统调用号,放在eax中;同时eax也存放返回值。ebx,ecx,edx存放3个参数*/
void sched_init(void) { set_system_gate(0x80,&system_call); } 用于设置0x80的中断处理linux/include/asm/system.h
#define set_system_gate(n, addr) _set_gate(&ide ,15,3,addr); idt是中断向量表基址 #difine _set_gate(gate_addr, type, dp1, addr) __asm__("movw %%ax\n\t" "movw %0,%%dx\n\t" "mov1 %%eax,%1\n\t" "mov1 %%edx,%2"::"i"((short)(0x8000+(dpl<<13)+type<<8))), "o"(*((char *)(gate_addr))), "o"(*(4+(char *)(gate_addr))),"d"((char *)(addr),"a"(0x00080000))linux/kernel/system_call.s
nr_system_calls=72 .globl _system_call /* 中断处理程序 */ _system_call: cmpl $nr_system_calls-1,%eax /* %eax存放系统调用号 */ ja bad_sys_call push %ds push %es push %fs push1 %edx push1 %ecx push1 %ebx /* 调用的参数 */ mov1 $0x10,%edx mov %dx,%ds mov %ds,%es /* 内核数据 */ mov1 $0x17,%edx mov %dx,%fs /* fs找到用户数据 */ call _system_call_table(,%eax,4) /* ex:a(,%eax,4)=a+4*eax */ push1 %eax /* 返回值压栈,被ret_from_sys_call使用 */ ... ret_from_sys_call: popl %eax,(其他的pop),iret
_sys_call_table+4*%eax 即为相应系统调用处理函数的入口include/linux/sys.h
fn_ptr _sys_call_table[]= /* _system_call_table是一个全局函数数组 */ { sys_setup, sys_exit, sys_fork, sys_read, sys_write,... };include/linux/sched.h
typedef int (fn_ptr *)();call sys_table(,%eax,4)即为 call sys_write
用户态 | 内核态 | |||||||||
printf 用户调用 | -> | printf 展成int 0x80 | -> | system_call 中断处理 | -> | sys_call_table 查表 | -> | __NR_write=4 | -> | 调用 sys_write |
相关文章推荐
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- 随笔:操作系统:系统调用的实现
- Linux操作系统下,通过系统调用和库函数分别实现对文件的拷贝
- [No000036]操作系统Operating Systems系统调用的实现System_Call
- 有些应用软件进行系统调用时,为了一些场景更好的实现最优的表现,因此需要调整操作系统参数:
- 【操作系统】编程技术--系统调用实现机理
- 假定某系统提供硬件的访管指令(例如形式:“svc n”),为了实现系统调用,系统设计者应做哪些工作?用户又如如何请求操作系统服务?
- 操作系统设计与实现--系统调用