优秀的编程知识分享平台

网站首页 > 技术文章 正文

计算机组成原理(41): 分时之六——超级用户调用SVC

nanyue 2024-11-10 10:17:26 技术文章 1 ℃

用OS通信

1.1 问题的提出

用户模式程序需要用OS进行通信来请求服务或访问有用的操作系统数据(如TOD)。

  • 访问虚拟I/O设备
  • 和其他进程通信
  • ……

但是用户模式程序和操作系统分别在不同的MMU上下文中运行(操作系统是内核模式,不是用户模式的虚拟地址空间),用户模式的程序不可能直接访问操作系统代码和数据。

那么用户模式的程序该如何访问操作系统代码和数据?

1.2 解决办法

  • 抽象:一个带有参数的超级用户调用(SVC),参数值在寄存器中,调用的结果在寄存器R0中或用户模式的内存UserMState 中返回。这种接口的一个实例是POSIX,它是由许多类似Unix操作系统的实现的标准接口。
  • 实现:用户模式程序使用非法指令产生一个异常中断,操作系统的中断处理程序实现用户请求的代码或数据。这样用户程序只需要执行一条非法指令即可实现与操作系统的通信。我们将采用使用操作码为1(opcode=1)作为产生异常的非法指令,作为“唤起”超级用户调用的“电话”。这些SVC指令的低位将包含一个索引,指示使用哪一个SVC。

操作系统SVC的组织

上图是用户模式/内核模式图。

  • 当执行SVC指令时,硬件会将1的操作码视为非法指令并触发OS非法指令异常处理程序,如我们在上一篇中讲的一样。如图中1
  • 处理程序将进程状态保存到临时存储区,如图中2,然后分派到基于操作码字段的适当处理程序。
  • 该处理程序可以访问临时存储区中的用户寄存器,也可以使用OS适当的子例程访问访问临时存储区。如图中3
  • 如果要将信息返回给用户,则返回值可以保存在临时存储区的R0寄存器中,如图中4
  • 处理程序完成后,可能会更新的已保存寄存器值被重新加载到CPU的寄存器中以恢复用户模式进程的执行,如图中5

SVC处理程序

在前面我们看到了非法指令处理程序如何使用调度表。

在下面的代码中,使用指令中的低位访问一个调度表已选择8个可能的SVCs中的每一个适当代码,选择完成后,通过JMP指令执行SVC子例程。

上面的SVC仅仅是示例少量简单的服务,真正的操作系统的SVC,用于访问文件、处理网络连接、管理虚拟内存、产生新进程…等等

返回用户模式

下面是当SVC处理程序恢复用户模式的代码。

在上述代码中,

  • 黄底色的代码是当SVC处理程序恢复用户模式进程时的代码,只需恢复寄存器的保存值,并跳转到被中断的程序断点处处重新执行。
  • 青底色的代码是由于某种原因SVC请求无法完成并且该请求会在未来重试。例如:ReadCH SVC返回用户键入的下一个字符,但是如果没有字符驶入,操作系统此时无法完成请求。在这种情况下,SVC处理程序应分支到I_Wait ,后者安排SVC指令在下次运行时重新执行,然后调用Scheduler运行下一个用户模式进程。这使所有其他进程会有机会在再次尝试SVC之前运行成功。
  • 此处代码还可以用作两个不同的SVC实现:进程可以通过调用Yield() SVC命令放弃当前执行时间的剩余部分,这导致操作系统指示简单调用Scheduler(),从而暂停当前进程的执行,直到轮询调度过程中的下一轮
  • 为了停止执行,进程可以调用Halt() SVC,看一下代码,可以看到“停止”有点用词不当,真正发生的是,系统安排每次重新执行Halt() SVC,然后使OS调度下一个要执行的进程。由于从未执行过Halt() SVC之后的指令,因此该进程似乎停止了。

添加新的SVC

添加新的SVC处理程序非常简单。

5.1 定义新的SVC宏

代码如下:

  • 黄底色的代码定义新的SVC宏以用在用户模式的程序中。在上述例子中我们定义了获取和设置TOD的SVC。
  • 这是第8和第9个SVC,见青底色代码和调度表 。因此我们要设置SVC调度代码,然后将各自代码的第一条指令的地址添加到调度表 的末尾

5.2 定义新的SVC处理程序

新的SVC处理程序同样简单明了,如下:

SVC小结

SVC机制为用户模式下的程序提供了对OS服务和数据的受控访问。

因为内核模式下禁止中断产生,利用这一特性,我们可以设计出不被其他进程干扰的功能模块。举个例子:

  • 若需要用LD/ADDC/ST的指令序列增加主内存中的值,而且希望LD和ST之间的执行不被其他进程干预。在用户模式下是不可能做到的,因为中断可以发生在任何指令上。
  • 我们可以将所需要的功能封装为SVC,然后再调用SVC,这样就可以确保LD和ST之间的执行不被中断。

Tags:

最近发表
标签列表