操作系统笔记(三)

您所在的位置:网站首页 系统调用的作用和目的 操作系统笔记(三)

操作系统笔记(三)

2023-09-09 15:17| 来源: 网络整理| 查看: 265

系统调用的实现 前言系统调用的直观实现内核(用户)态,内核(用户)段处理器保护环将其分为了四部分对于内核段代码的处理用段寄存器来进行解决 硬件提供了“主动进入内核的方法”系统调用的核心 int 0x80拿Write函数举例函数内部发生了什么int 0x80中断的处理中断处理程序小结

前言

前面的文章说了什么是系统调用,就是系统提供给上层用户的一些函数,如open,read,write…,表面上是一些函数,背后是如何实现的呢? 这一篇文章就会记录系统调用是如何实现的。

系统调用的直观实现

反正所想要打印的代码与系统代码都在内存里,直接跳转,直接调用不可以吗? 答:肯定是不能的。 不能随意的调用内核的数据;不能随意的jmp。 如果能的话,操作系统内的很多重要的东西,比如root用户的密码,就不安全了。 所以系统调用就提供了一种可以进入内核的一种手段。

内核(用户)态,内核(用户)段

将内核程序和用户程序隔离!! 区分内核态和用户态:一种处理器“硬件设计”

处理器保护环将其分为了四部分

最内层0,为核心态。 中间两层1、2,为OS服务。 最外层3,为用户态。 当前程序执行在什么态(哪层环?)由于CS:IP是当前指令。所以用CS的最低两位来表示:0是内核态,3是用户态。 内核态可以访问任何数据,用户态不能访问内核数据。 对于指令跳转也一样,实现了隔离。

对于内核段代码的处理用段寄存器来进行解决 1. CPL(CS) 当前的特权级 current 取决于当前执行的什么指令 2. RPL(DS) 访问的数据段DS的最低两位 3. DPL 用来描述目标内存段的特权级 D目标 P特权 L级别 (DPL在GDT表中 可以找到) 4. DPL在GDT表中的级别都为0 意为内核段 5. 数字越大 特权级越低!! 只有当前的特权级>=要访问的mov的特权级,指令才可以jmp 硬件提供了“主动进入内核的方法”

对于Intel x86,那就是中断指令int int指令将使CS中的CPL改成0,“进入内核”

这是用户程序发起的调用内核代码的唯一方式。此时,CPL=3,而DPL=0。

系统调用的核心 int 0x80

(1)用户程序中包含一段包含int指令的代码 由谁做?库函数 (2)操作系统写中断处理函数,获取想调程序的编号 (3)操作系统根据编号执行相应代码

拿Write函数举例 函数内部发生了什么 在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(__ress>=0) return(type)__res; errno = -__res; return -1; }

显然,__NR_write是系统调用号,放在eax中。

在linux/include/unistd.h中 #define __NR_write_4 //一堆连续正整数(数组下标,函数表索引)

同时eax也存放返回值,ebx,ecx,edx存放3个参数。

int 0x80中断的处理 void sched_init(void) { set_system_gate(0x80,&system_call); }

显然,set_system_gate用来设置0x80的中断处理

在linux/include/asm/system.h中 #define set_system_gate(n,addr) \ _set_gate(&idt[n],15,3,addr); //idt是中断向量表基址 #define _set_gate(gate_addr, type, dpl, addr)\ // 把dpl置为3 __asm__("movw %%dx,%%ax\n\t" "movw %0,%%dx\n\t"\ "movl %%eax,%1\n\t" "movl %%edx,%2":\ :"i"((short)(0x8000+(dpl


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3