哈工大操作系统学习笔记二——系统调用的实现

哈工大os学习笔记二(系统调用的实现)

第二篇笔记 操作系统的调用


一、三个问题

 1.应用程序为什么不能直接访问操作系统,而必须通过接口?

在这里插入图片描述
osl内的很重要,如root用户密码,假如网上下载的一个代码能直接访问,就能获取root,或者是随意更改计算机的配置,不安全,不好管理。

 2.怎么才能不直接进入内核?

在这里插入图片描述

请添加图片描述

只有硬件设计,才能不让应用程序直接进入内核。

计算机对内存的使用都是一段一段的使用


而这个硬件设计,靠段寄存器实现(CS DS)
只要明白CPL,DPL
初始化的时候DPL就在GDT表中,而操作系统数据段代码段对应的DPL都为0
DPL:是用来描述目标内存段的特权级别,也就是要跳往的访问的
CPL:是用来描述当前的特权级,取决于执行的是什么指令 ,执行指令都要有pc(CS:IP)
cs表示一段内存区 ,cs中的一部分表示当前程序所处于的特权级
目标特权级的数字要大于或等于当前特权级的数字(DPL>=CPL)
这种特权级也叫保护环/特权环
在这里插入图片描述
在这里插入图片描述

小结:

  1. 在OS初始化的时候(head.s执行的时候)会针对内核态的代码和数据建立GDT表向,然后他对应的DPL就等于0(当时已经初始化好了0)DPL在GDT中
  2. 最后转到用户态进行执行,启动用户执行程序,cs里的CPL=3,这个CPL=3也是初始化时候设置的,(推到用户态时候设成3)之后就一直保持3
  3. 当跳到内核时候CPL=0,回到用户时候CPL就又等于3
  4. 每一次跳转移动(jmp,mov)都要访问GDT表,因为访问段寄存器嘛,要通过段进入内核
  5. 这时候检查DPL>=CPL?
  6. 由于DPL=0,CPL=3 直接挡住不让进

 3.那要通过什么方式进入内核?

接上面,既然不让进去,那怎么访问呢?

在这里插入图片描述

硬件提供主动进入内核的方法——中断指令int
并不是所有的中断都能进入内核,只有硬件专门 设计的一部分才能进入内核
系统调用就是上层应用调用操作系统提供的接口(一些函数)。中断(系统调用使用int 0x80)是硬件提供的用户态进入内核态的唯一方式。
在这里插入图片描述

二、系统调用的详细过程:

说白了就是接口的参数转换,上一个接口函数的参数怎么转换成下面的接口函数的参数

1.首先我们应用程序调用printf("%s",…)
2.在C库函数中变成printf():

由于下面要传给库函数write(…),所以要把应用程序调用的printf转化成write能接收的参数,PPT里显示了write传参的格式,所以要先经过c库函数printf(…)的中转变成write所需要的buf缓冲区,和字符个数。

3.在调用write(…)变成一段包含int 0x80 的中断代码
4.然后中断再通过系统调用,进入操作系统里面

三、 系统调用细节:

在这里插入图片描述
在这里插入图片描述把系统调用号__NR_write写入eax寄存器,并在ebx,ecx,edx寄存器中传入参数,调用int 0x80号中断进入内核完成系统调用。
系统调用号置给%eax,然后调用int 0x80,调用int 0x80就到内核了,所以下面就要明白int 0x80是什么

 int 0x80中断的处理

int 0x80查IDT表
由于大家都是从int 0x80接口进入的,所以设置系统调用号作为具体导向。
在这里插入图片描述
初始化时候做的,int 0x80通过system_call这个函数进行处理
怎么做到的,设置system_gate中断处理门
实际每一个表向就是中断处理门
在这里插入图片描述

int 0x80需要查询中断表IDT,找到对应的中断门。而内核初始化的时候,恰好设置了0x80号中断对应的中断门。在文件linux/init/main.c中132行调用了sched_init()函数,而sched_init()函数在linux/kernel/sched.c中,sched_init()函数最后一行代码就是设置0x80号对应的中断门描述符,如下图。
在这里插入图片描述

set_system_gate在linux/include/asm/system.h中,如下,就是设置中断门描述符的,段选择子设为0x8,段内偏移设置为&system_call(中断处理函数地址),DPL设为了3。而用户态CPL=3,正好可使用该中断门,而该中断门里面的段选择子是0x8,0x8对应的二进制是b0000_0000_0000_1_0_00,对应的CPL=0,于是乎进入内核态。在中断程序执行完之后,CPL会设置为3,回到用户态。

在这里插入图片描述
在这里插入图片描述

这时cs =8, ip=&system_call
0x8=b0000_0000_0000_1_0_00 cs最后为00,而cs最后两位为cpl,所以cpl=0,当前特权级为0,现在在通过中断以后,然后在执行中断处理程序的时候就就是特权级为0 了,就到内核态进行执行了。

回顾一下,在初始化的时候DPL设置为0,在初始化的时候80号中断的DPL设置成3,故意让cpl为3的用户能进来,进来后cpl就设置为0了。就进入内核了
在返回的时候会执行一条指令,这条指令将cpl又设为3,就又变成用户态

 接下来是中断处理程序system_call

中断处理程序就是linux/kernel/system_call.s,如下。
在这里插入图片描述在linux/include/linux/sys.h中,对应了系统调用的所有函数列表,如下。
在这里插入图片描述
_sys_call_table函数指针数组
在这里插入图片描述
call _system_call_table (,&eax,4) //a(,%eax,4)=a+4*eax
_sys_call_table+4/eax*就是相应系统调用处理函数入口
call _system_call_table (,&eax,4) 就是call sys_write

到此,就要开始真正去调用sys_write了,而sys_write内部是怎么样的呢?后面课程会讲。

在这里插入图片描述

系统调用大致过程

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值