爱体育官方app  
重庆 | 北京 | 深圳 | 上海 | 成都 | 宁波
全国服务热线: 400-023-8112 15111998399
爱体育官方app
爱体育官方app
公司新闻
常见问题
 

地址:重庆市石桥铺一城精英国际大厦12-2室
电话:023-61170788  
手机:15111998399(24小时)
全国免费热线:400-023-8112
QQ:53755635

公司新闻
   

爱体育官方app:操作系统学习笔记2 操作系统接口

发布时间:2022-08-17 06:34:37 来源:爱体育安装 作者:爱体育手机版

  这部分将讲解上层应用软件如何与操作系统交互,理解操作系统到底发生了什么事情,理解操作系统工作原理,为以后扩充操作系统、设计操作系统铺垫。

  正如生活中的接口,对于上层来讲,接口的存在是十分自然的,当我们有某项需求,才会使用响应接口

  说明: linux0.11只有命令行,而没有图形界面linux有图形界面是比较新的版本如ubuntuWindows也有可以尝试在linux0.11上实现图形界面

  从上面可以知道,命令行和图形按钮都是一些程序,就是普通的C程序,只是在C的基础上使用了一些重要的函数,这些函数可以进入操作系统、使用硬件

  printf,实际printf在库中调用了write,后者是真正的接口

  :Portable Operating System Interface of Unix;这是一个手册,可以在这里查系统调用;也可以从这里得知设计一个操作系统应当提供的基本接口,这样在Linux上、Windows上跑的应用也可以在我的系统上跑。这就为上层应用程序跨操作系统提供了可能,因为调用接口一样。

  应用程序main()在内存中,操作系统whoami()也在内存中,为什么不能直接访问存放用户名这个字符串的内存呢?

  如果上面的事情被允许,上层应用程序(可能来自于网络),就可以得知你的root用户名和密码,可以修改它。

  此外,任何一种输出数据到外设的系统调用,在某个时刻,这些数据会在操作系统内核的缓冲区中,这个时候就可能被泄漏,比如可以通过缓冲区或者显存看到word软件里面的内容;

  处理器硬件将内存访问权力(主要)分为了用户态和核心态。对应的实际区域即用户段和内核段。指令在两段之间不能随意跳转。

  RPL说明的是进程对段访问的请求权限(Request Privilege Level)

  ,destination privilege level也称 descriptor privilege level,之所以称为目标,是因为它描述程序将要跳往的地方的特权级;

  CPL意思是当前内存段的特权级,current privilege level,CS:IP指向当前要执行的指令地址,

  当前程序处于内核态还是用户态(CPL),用CS:IP的最低两位来表示。

  特权级,特权级有一个数字,数字的含义可见下图处理器保护环;数字越小,越接近内核。

  特权级是在操作系统初始化时就设置好了的;DPL就在GDT表中,GDT表中第45、46位就是DPL。head.s 初始化时全为0。在系统最后启动用户应用程序时,跳转后cs中的CPL就置为3了。

  CPL就是CS的最低两位,DPL可以从GDT表中查到,在保护模式下指令地址的翻译是查GDT表,那么这个时候就可以查到目标指令的DPL,和当前态的特权级CPL比较,如果DPL=CPL,那就说明当前态的特权级足以执行目标指令,否则就不允许执行

  回到例子。所以例子中的main()程序CPL=3,而目标whoami()DPL为0,所以不能跳转,也即不能从用户态直接访问内核。

  whoami在内核态加载,main在用户态加载,main调用whoami相当于用户态jmp到内核态

  当然,上面的举例基于linux0.11。操作系统现在基本不依靠段来进行权限检查 以页保护为主进行权限检查

  前面提到过了不能直接访问内核,不应该直接访问内核,计算机是如何做到这种隔离的,下面就来看看在这种隔离下,系统调用如何实现跨越特权级的访问。

  对于 Intel ×86 来说,进入内核的唯一方法是中断指令int,其他如jmp和mov都不行。

  表面上是open()函数,展开后是由包含int指令的C语言库函数做的。

  问:为什么不能在普通代码里直接使用这个特殊中断进入内核? 答:不使用封装的库函数,直接写int中断编译不通过(可能是编译器的设计)。 以C代码库编写的系统调用,在用户程序调用后,会首先进入C代码库函数,然后用汇编代码在约定的位置(栈或者寄存器)设置参数和系统调用编号,最后执行int指令

  所以举例whoami() 中的printf()很复杂,它的实现在软件层面跨越了三个层次:

  将关于write的故事完整的讲完,看看int 0x80 到底做了什么事情,以及是如何做到的。

  宏展开:C语言中的宏展开 ,可以简单理解为文本替换,相比于C基础中的宏定义,这个宏能够替代一段程序。

  上面的_syscall3的3的意思就是:有三个参数。只要都是3个参数都可以使用这部分代码的套路。

  初始化一个描述 int 0x80 中断的门描述符,并添加到IDT表,门描述符中的段选择符是0x0008,可以定位到GDT表的第二个表项,即内核代码段

  上部分大致讲了write库函数的展开与实现过程,其中int 0x80还没有细说,现在看看这个指令是如何工作的。

  ,而库函数write()通过一个宏,内嵌了一段包含核心0x80的汇编代码

  ) 保存是因为什么到达 0x80 这个入口的,方便操作系统来进行对应的操作。比方说这里是 write 使用了0x80.。

  处理结束后再返回,这时0x80就已经完成,接着进行=a(__res)把 eax 赋给 res

  hide codemov1 $0x10,%edx mov %dx,%ds mov %dx,%es ## 内核数据 ###ds=es=0x10 ###8是内核代码段,16(十进制)是内核数据段 ###意味着从现在开始真正执行内核代码 ###这里有疑问,老师说,既是内核代码段也是数据段? ## 跳到一个表里取执行内核代码 call _sys_call_table(,%eax,4)#a(,%eax,4)=a+4*eax ### eax正是前面的__NR_write,系统调用号 ### _sys_call_table+4*%eax就是响应的调用处理函数入口为什么要乘4呢? eax是4(表示write的系统调用号为4,为第四系统调用) 而前面的4是,每个系统调用占4个字节。 再具体一点说,每个系统调用函数指针是4个字节 一个内存地址对应8位就是一个内存地址存1个字节,所以*4就是找4个字节中断号为4,那从中断向量表里找中断服务函数入口的时候就是4*4,即从表的初始地址往下加16个地址,就正好是16个字节,每四个字节一个入口 可以理解/推测 sys_call_table,就是一个函数表3.7 sys_call_table/sys_write理解

  从上面代码得知,_sys_call_table果然是一个函数指针数组,第4个位置上放的是sys_write。

  我们已经推进到了sys_write,也就是接口的边界,再向内部,才能解释sys_write 最后发生了什么。

 
 
友情链接:

XML地图|版权所有:{爱体育官方app 地址:重庆市石桥铺一城精英国际大厦12-2室 电话:023-61170788 手机:15111998399(24小时)
《中华人民共和国电信与信息服务业务经营许可证》编号:黑ICP备68300241号-1
重庆网站建设|爱体育官方app提供技术支持|网站地图

爱体育官方app

公网安备 50010702500980号