建立系统调用

1、为系统应用程序增加系统调用接口

将进程切换到level3后,进程对操作系统的代码和数据访问不能直接进行,权限不够。具体表现为会检查CS和DS中相关的权限位,当发现权限不够时,硬件将会触发异常,然后由操作系统处理这个异常,比如杀死进程。

此外,前面设置的分页机制中也支持权限处理,即通过U/S位设置是否允许应用程序是否访问。当其值为0时,限定只允许操作系统访问。

系统调用并不只是执行代码,还需要请求操作系统完成某些工作,比如读取磁盘上的文件。采x86硬件提供的调用门去完成,通过调用门,应用程序能够请求操作系统调用其内部的某个函数。

具体流程:

  1. 配置GDT表:在GDT表中配置好相应的调用门描述符。包括调用门权限、不同特权级之间拷贝的参数个数、被调用函数所在代码段、被调用函数所在代码段中的偏移。
  2. 执行系统调用:使用Call指令,硬件会自动从调用门中取出操作系统中相应函数的入口地址
  3. 参数传递:自动压栈,同时从原调用栈中拷贝参数到新栈
  4. 执行被调函数
  5. 执行ret指令返回

在使用之前,需要先在GDT表中配置好相应的调用门描述符

当执行系统调用时,使用call指令即可,硬件会自动从调用门中取出操作系统中相应函数的入口地址

与此同时,还会进行参数的传递。参数传递的过程与【前置课】中介绍的一致。

采用调用门的好处就是硬件会自动将参数复制到内核中。在向被调用的操作系统

2、实现sys_sleep系统调用

由于只使用一个调用,因此需要通过额外的参数来指示当前要调用的是那个系统函数。具体的话是:定义了一个sys_table来存储系统调用的函数表。然后在执行系统调用时,从传入的参数中获得需要调用的函数对应的id。再利用该id查找表取得函数入口指针,进而调用该函数。

为了取得系统调用传入的函数,课程定义了syscall_frame_t结构来解析栈中的寄存器和参数值,通过该结构体,即可获得系统调用传入的参数,以及当前执行系统调用时的状态。

根据GCC对函数返回值的处理规则:函数调用的返回值保存在eax寄存器中,在系统调用之后,执行frame->eax=ret,用于将执行结果返回给应用程序。

3、使用int $0x80 实现系统调用

实现系统调用除了使用调用门之外,还有其他方式:比如任务门、中断门。因此,可以自行执行int序号来触发一个中断门对应的处理程序执行。

使用向量号为0x80的中断门,当需要执行系统调用时,执行int 0x80指令,参数也是通过寄存器传递。调用门使用压栈和出栈来实现

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值