Linux0.00内核为什么要自己设置0x80号陷阱门来调用write_char过程?
我一开始没注意这个问题,只是通过陷阱门觉得很绕弯子,为何不在3级用户代码里直接调用write_char,今天自己写程序想用call调用代码段,才发现了大问题。我写了个类似于write_char的过程,代码如下:
dividing_line:push %gspushl %ebxpushl %ecxmovl $10,%ecx/*输出10个空格' '*/movl $SCRN_SEL,%ebxmovw %bx,%gs
1: movl scr_loc,%ebxshl $1,%ebxmovb $32,%gs:(%ebx)/*' '空格ASCII码*/shr $1,%ebxincl %ebxcmpl $2000,%ebxjb 2fmovl $0,%ebx
2: movl %ebx,scr_locloop 1bpopl %ecxpopl %ebxpop %gsret
其功能为在屏幕上输出10个空格而已。简直和write_char几乎一样,只不过我指定了要输出的字符,不是通过ax获取罢了。还有一个不同就是我要通过call来调用dividing_line,而不是像write_char一样被陷阱门调用。
结果程序挂了,没法运行。
后来分析了下,原因很简单。我在task1里面直接调用write_char也是不行。这两者原因是相同的,那就是这两行代码:
movl $SCRN_SEL,%ebx
movw %bx,%gs
在源代码中SCRN_SEL= 0x18是GDT中显示数据段的selector,甭管他是什么数据段,反正他是数据段就对了,这个数据段描述符DPL=0,属于高特权级,但是我们现在用特权级3级的代码去调用这个过程,那么这个处理过程此时就算作3级程序的一员,即他的特权级也是3级,CPL=3,尽管SCRN_SEL= 0x18中的RPL=0,但是CPL不够级别,这种加载SCRN_SEL= 0x18的请求必将被处理器驳回。处理器在加载selector进段寄存器时会将当前运作程序的CPL、selector的RPL、被指向描述符的DPL做综合比较,除非CPL和RPL在数值上都小于DPL,也就是特权级较高。否则,这种加载selector的行为都将被处理器拦截并产生保护异常。
回到我的程序,所以只要这个加载0x18 这个selector的行为存在,这个过程的调用就必然失败,因为0x18 这个selector所指向的数据段描述符DPL超高。于是乎,在3级程序里直接调用write_char也好,dividing_line也好,都会失败,无权访问此数据段,有意图也不行。
这就是为什么要通过陷阱门去调用write_char,处理器规定通过陷阱门只能向高特权级代码段转移,不得转入低特权级代码段,意思就是我从3级用户代码转入内核0级代码这是天经地义的。但是注意,3级代码的确可以通过陷阱门转入0级代码,但前提是陷阱门的门描述符DPL=3才行。不然用户程序根本没权限去访问陷阱门。好了,我们假设陷阱门描述符DPL=3,陷阱门描述符里面的目标代码selector指向一段内核0级代码。
这样当3级程序去加载陷阱门描述符,完全可行,因为CPL=3,我们再用RPL=3的selector去访问陷阱门,陷阱门DPL=3,这样完全可以访问陷阱门。然后陷阱门里面的目标selector部分指向0级代码,这没有关系,通过陷阱门我们完全可以转过去,处理器就要我们这样做!这才是应该的过程。低级程序访问低级陷阱门,低级陷阱门里有高特权级的代码段selector,这样可以通过陷阱门转入高特权级的内核代码当中去。这为一些系统调用提供了方便。
最后有一点,我们把这两行导致问题的代码去掉,能不能正常调用呢?答案是肯定的,既然把这两行去了,那么这个处理过程的功能就废了,好不如写个简单点的,比如:
example:pushl %eaxmovl $0x250,%eaxpop %eaxret
这个够简单,在3级用户代码里call example就可以调用了,没有输出提示所以我们可以通过bochs调试来确认,结果就是调用成功,执行过程成功进入此example代码。这就是个普通近调用,没啥特殊的。关于陷阱门特权级我们就说到这里。
说完了。
转载于:https://blog.51cto.com/mirage1993/1576602
Linux0.00内核为什么要自己设置0x80号陷阱门来调用write_char过程?相关推荐
- Linux0.11内核--系统中断处理程序int 0x80实现原理
系统调用是一个软中断,中断号是0x80,它是上层应用程序与Linux系统内核进行交互通信的唯一接口. 这个中断的设置在kernel/sched.c中441行函数中 void sched_init(vo ...
- 仿制Linux0.00编写拜年系统
首先看下效果 源代码 Makefile AS=as LD=ld CC=gcc LDFLAGS=-s -x --oformat binary CCFLAGS=-m32 -fno-pic NM=nmall ...
- Linux0.11内核源码解析-setup.s
学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->setup程序将system模块从0x10000~0x8ffff整块向下移 ...
- Linux0.00 代码解析(二)
Linux 0.00 的编译.运行.源码下载: http://blog.csdn.net/longintchar/article/details/78757065 Linux 0.00 Makefil ...
- Linux0.11内核剖析--内核体系结构
一个完整可用的操作系统主要由 4 部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如下图所示: 用户应用程序是指那些字处理程序. Internet 浏览器程序或用户自行编制的各种应用程序: ...
- Linux-0.11内核学习-添加系统调用
1.参考资料 赵炯博士的网站oldlinux Linux内核完全注释 Linux0.11 源码 2.概要 操作系统作为软件应用层和底层硬件之间的部分,向下提供服务,向上提供接口.系统调用便是操作系统向 ...
- 一站式linux0.11内核head.s代码段图表详解
阅读本文章需要的基础: 计算机组成原理:针对8086,80386CPU架构的计算机硬件体系要有清楚的认知,我们都知道操作系统是用来管理硬件的,那我们就要对本版本的操作系统所依赖的硬件体系有系统的了解, ...
- LINUX0.11内核阅读笔记
我是通过阅读赵炯老师编的厚厚的linux内核完全剖析看完LINUX0.11的代码,不得不发自内心的说Linus真的是个天才.虽然我觉得很多OS设计的思想他是从UNIX学来的,但是他自己很周全很漂亮很巧 ...
- VirtualBox虚拟机安装RedHat7.3编译Linux0.01内核
引子 由于需要编译linux0.01内核,而目前的linux版本太高需要降低gcc版本等等,需要做不少调整非常不方便. 所以,直接安装RedHat7.3,这样就好编译linux0.01的内核了. 但是 ...
最新文章
- 如何使用 Python 操作 Git 代码?GitPython 入门介绍
- Python的控制语句4
- java不同网址提示过期_使用history.back()出现警告: 网页已过期的解决办法
- tomcat源码 Connector
- java学习(64):类访问私有内部内部类方法
- 【C++深度剖析教程27】多态的概念与意义
- idea+JRebel实现项目热部署
- 终于……我的游戏………简体版就要发布了!
- Jmeter设置代理,抓包之app请求
- linux如何导入种子文件格式,Linux下磁力链接种子文件下载
- openwrt中的mt7621、MAC存储、PPP、UCI、ubus
- NOIP2016排名(1~745)
- 解决isilon网络配置界面无配置显示
- 底量超顶量超级大黑马指标源码_清华女教授忠言:只要出现“底量超顶量”走势,后期必有暴走趋势...
- 华为nova5iotg功能使用_华为nova3怎么使用OTG功能教程,华为nova3 OTG功能详解
- 机器视觉镜头的计算方法
- maven的资源过滤filters
- CDC Schemes
- rtx3080ti参数 rtx3080ti什么水平 rtx3080ti评测
- linux运维自动化脚本,linux运维自动化shell脚本小工具