系统调用的实现原理

实模式和保护模式 

在计算机科学中,实模式和保护模式用来描述CPU是否在安全上控制程序对内存访问。在实模式下,程序是没有被控制的,选址方式采用段寄存器(16bit)+偏移地址(4bit);在保护模式下CPU的x86架构定义了严格的控制模式,段寄存器里保存的是GDT(段描述符表),段地址保存在了内存中,寄存器只是一个内存索引。GDT是一个数据结构,里面保存了各类段描述符GD,相对于的还有LDT(局部描述符表)。

 

保护模式下的特权级别

我们常常说保护模式有特权级别,它是一个环状,ring0~ring3,在保护模式下复杂的地址转换中是如何实现ring0~ring3的控制呢?

保护模式的特权级别的校验在三个地方:
  1 GDT表项中的字段DPL,它表述当前段的级别
  2 CS寄存器中,寄存器不仅仅就是一个索引吗,是的,不过不是全部的字段都用于索引,其中有一个CPL字段,表述的是current privilege level,当前允许的级别
  3 段选择子,selector,这是最困扰我的地方,后来发现他仅仅是CDT的偏移,用来找到正确的段描述符,GDT是一个表,正真的段偏移地址是其中的一个表项,而selector是偏移地址。好了selector也并不是所有字段都是偏移,其中有一个字段为RPL,请求权限级别,我觉得这里有点点多余。

在保护模式下是不允许直接修改CS寄存器的,那么怎么实现不同特权级别间的迁移呢?曾今一直困扰着我一个问题,中断到底是什么?它为什么可以控制从ring3到ring0,如果这样的话,我们不是可以在ring3下调用汇编代码变成ring0,之后就可以控制整个计算机了?
stackoverflow上有一个同学和我一样陷入了矛盾论中,我们看看:
http://stackoverflow.com/questions/19057503/switching-from-user-mode-to-kernel-mode


从高级别权限可以任意的进入低级别权限中(在高级别权jmp到低级别的代码段即可,CS的CPL flag会跟着变),而一旦进入低级别,你想回来?没门,或者说有一个门(门描述符GATE)可以让你回来,但你执行的代码被限定了,这些代码段是你第一次在高级别权限下定义的,例如中断处理函数。

特权级别的安全控制的哲学原理是,在创世纪初期(启动计算机)你拥有至高无上的权利(ring0),你必须将这个世界的基本运作规则(系统调用函数、硬件操作函数)设计好,一旦完成你将进入凡人阶段(ring3),你平庸的生活着(在用户空间),有时你需要上帝的指引(系统调用),但你无法修改这些规则,而只是在平凡生活中按照制定好的规则使用,使用完成后你又马上变回(因为每次都是调用,ret时,自动回到ring3)凡人状态(ring3);

我们看到的门调用(call gate)、中断处理(trap、interrupt)等等都是

参考:在一个操作系统的实现

 

--------------------------------------以下是我之前的理解,但还是太浅------------------------------------------------

前段时间我一直纠结在操作系统是如何system call的。因为在system call中代码的权力是至高无常的ring0级别,可以访问、读写内存的任何部分。
  如果任何一个人写一段代码获取这个ring0,再去执行他定义好的代码,那岂不是一切都被破解了。
  一 cpu中用于安全控制的主要实体
  1 cs寄存器,这个寄存器有两个字节标示ring级别,叫做CPL(current privilege level),
     cpu的特权控制的关键点就在此,在执行某一段代码时,cpu会去用这个CPL去比较段描述符、页表项属性等等,如果级别不够,就会出现禁止访问。
   2 IDT 中断描述符表,cpu硬件天生就知道IDT的位置,据说是保存在某个寄存器中,在实模式下被初始化的。最后跳到保护模式。
      这个中断描述符表中存储了中断处理函数的地址,1-32是硬件中断,后面的是软件中断。
      中断描述符表中也有一个flag,表明谁可以执行这段代码,这个描述符的128使我们的所有系统调用如何,并且在IDT中对这段的控制是放在ring3的,也就是任何人都可以调用。
   那么我们调用fork,在汇编中看到int 0x80,cpu发生中断,去调用128函数,这个时候控制了ring的切换,这就是cpu硬件的级别的唯一控制方法吧。

你可能感兴趣的:(操作系统)