现在的位置: 首页 > 综合 > 正文

嵌入式实时Hypervisor:XtratuM (7)

2018年04月28日 ⁄ 综合 ⁄ 共 3088字 ⁄ 字号 评论关闭

 

1.1           Hypercall

系统调用是通用操作系统提供的一种重要机制,系统调用将操作系统分为两个部分:内核空间和用户空间。用户程序可以通过系统调用接口从用户空间陷入内核空间,这种机制有助于虚拟内存的实现,并且还可以提高系统的可靠性、安全性、健壮性。在XtratuM系统中,Hypercall是一种类似于系统调用的机制,它是上层域从用户空间陷入Hypervisor Kernel的接口。在XtratuM系统中,XtratuM模块通过Linux提供的指令将其加载,并且让XtratuM内核与Linux内核运行于同一地址空间。为了将实时域与Linux内核空间相分离,在XtratuM内核与实时域之间建立一层Hypercall,实时域就是通过这层Hypercall访问底层资源。在Linux系统中,系统调用对应的陷阱号是0x80,由于要保留Linux这一特性,XtratuM Hypercall 对应的陷阱号是0x82。当前,XtratuM共支持11Hypercall。在XtratuM系统中,所有的Hypercalls被保存在一个Hypercall表中,如下段代码所示。

hypercall_handler_t

syscall_table [HYPERCALL_ENTRIES] = {

  exit_domain_sys,

  load_domain_sys,

  unload_domain_sys,

  suspend_domain_sys,

  sync_events_sys,

  pass_event_sys,

  get_time_sys,

  set_timer_sys,

  get_cpu_khz_sys,

  write_scr_sys,

  enable_hwirq_sys

};

用户新定义的Hypercall函数指针就可以添加到该表中中,但是要注意HYPERCALL_ENTRIES的数值以及对应Hypercall的调用号。HYPERCALL_ENTRIES应该大于等于Hypercall的个数,而Hypercall的调用号是给应用域使用。__syscall1就是客户域定义的能够实现具有一个参数的Hypercall的宏,其中包含参数值(arg1)Hypercall(name_nr),和返回值(__res),“int $0x82指令将会触发Hypercall陷阱,使系统由域空间进入XtratuM内核空间。__syscall1宏的代码如下。

#define __syscall1(arg1, name_nr, __res) /

  __asm__ __volatile__ ("int $0x82/n/t" /

                        : "=a" (__res) /

                        : "0" (name_nr),"b" ((long)(arg1)))

XtratuM系统中,存在六个类似__syscall1的宏,分别用来创建无参数、一个至五个参数的Hypercall。图2-5给出了PaRTiKle系统调用write_scr()的函数调用图。

 

图2-1.          write_scr() 调用函数树

1.2           任务管理

XtratuM系统,域是基本的调度单位,那么与通用操作系统中的进程或线程相比,有什么区别呢?本节中从域的定义、实现、以及XtratuM系统中的调度器和任务切换等方面介绍这一XtratuM系统中的基本运行单位。

1.2.1              域任务

(Domain)类似于进程或线程,是一种调度单位,但是与进程和线程相比,域具有更广泛的概念。域具有自己独立的物理资源,例如内存、并口等物理设备,以及其它的虚拟设备等。一个域中可以包含多个进程或线程,并且域具有内部调度器,可以根据需要调度域内任务。概括来说,域是一个具有私有软件和硬件资源的可调度单位,对资源有着更强更多的私有化,尤其是硬件资源,甚至可以将一个域对应为一个操作系统。

XtratuM系统,一个域由一个域结构体表示,主要包含私有物理内存、虚拟中断、虚拟时钟、虚拟内存、优先级等私有资源。其中私有物理内存构成私有栈,作为内存池为域内任务分配内存。每一个域中有32个虚拟中断,可以对其进行屏蔽、打开操作,具有已发生、已处理等状态。虚拟时钟可以用来模拟时钟周期和当前时刻。每一个域不仅具有物理内存,还具有私有虚拟内存空间。这种采用虚拟内存地址空间的策略,有助于实现XtratuM Hypervisor系统的HypercallsXtratuM系统可以为域分配1024个不同的优先级,Linux系统具有最低优先级(1023)。优先级作为域的重要资源,是任务调度器选择将要被调度任务的重要判断依据。图2-6给出了XtratuM系统中域的基本结构。

 

图2-2.          域的结构模型

1.2.2              调度器

上面一节已经介绍了优先级的概念,从理论的角度来说,它是域系统重要的表现方式,从实践的情况说,它是调度器选择可运行域和分配CPU资源的依据。XtratuM系统中,域具有四个状态:睡眠,就绪、运行、阻塞,其中阻塞的原因可能是被抢占或缺乏资源。图2-7给出了域的状态转换模型。

 

图2-3.          域状态转换模型

XtratuM的具有简单的基于优先级的可抢占实时调度策略,支持周期性和非周期性任务。通常,调度器由时钟中断和任务状态切换函数触发,调度器被触发后,主要完成:

1)      将中断向低优先级域传递。在XtratuM系统中,中断采用I-PIPE策略,这种管理方式类似管道,中断首先设置最高优先级的域,等高优先级域被调度和执行后,次优先级的域会将中断传递给更低优先级的域,然后执行次优先级任务,依次递归,直到所有的域对中断做出响应。这种管理方式可以保证低优先级的域即使中断服务也不会阻碍高优先级任务的执行,并且可以降低中断延迟,保证高优先级的域对中断进行最快服务。

2)      根据优先级大小,选择具有最高优先级的可运行域。在系统中,每一个域对应唯一的一个域结构体,它们在一个由优先级决定的链表中,优先级越高,对应的数值越小,越接近链表头。当域处于可运行状态或者是该域支持的中断发生时,该域就会被选中,获得CPU的使用权。

3)      任务切换,进入新任务。所为任务切换,实际上就是任务运行任务上下文的切换,主要包含代码段、数据段、和栈的切换,而这些内容的标记都保存在寄存器中,因此,任务切换的底层分析就是寄存器内容的转变。域任务切换的算法如下:

FUNCTION INT Domain_Context_Switch(old_domain, new_domain)

BEGINE

将通用寄存器压入栈(old_domain)

将浮点运算相关寄存器压入栈(old_domain)

切换地址空间(改变CR3寄存器的数值) (old_domain->new_domain)

将浮点寄存器弹出栈(new_domain)

将通用寄存器弹出栈(new_domain)

Return 0;

END {FUNCTION}

4)      中断服务。恐怕很多读者都很奇怪,为什么会将中断服务程序的相应放到任务切换模块中。主要有两个方面,首先,由于这里的中断是域系统的一个虚拟中断,系统刚刚切换到一个新域,对应于操作系统,中断应该在域中具有最高优先级,因此,在系统退出中断模式、进入域线程或进程时,中断应首先被调用;另外实现简单,不需要将域虚拟中断服务程序单独处理,避免了域内空间切换。

 

抱歉!评论已关闭.