码迷,mamicode.com
首页 > 系统相关 > 详细

Linux0.00内核为什么要自己设置0x80号陷阱门来调用write_char过程?

时间:2014-11-15 06:46:46      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:linux内核   陷阱门   0.00   

    我一开始没注意这个问题,只是通过陷阱门觉得很绕弯子,为何不在3级用户代码里直接调用write_char,今天自己写程序想用call调用代码段,才发现了大问题。我写了类似于write_char的过程,代码如下:

dividing_line:
	push %gs
	pushl %ebx
	pushl %ecx
	
	movl $1,%ecx/*输出1个空格‘  ‘*/
	movl $SCRN_SEL,%ebx
	movw %bx,%gs
1:	movl scr_loc,%ebx
	shl $1,%ebx
	movb $32,%gs:(%ebx)/*‘ ‘空格ASCII码*/
	shr $1,%ebx
	incl %ebx
	cmpl $2000,%ebx
	jb	2f
	movl $0,%ebx
2:	movl %ebx,scr_loc
	loop 1b

	popl %ecx
	popl %ebx
	pop %gs
	ret

    其功能为在屏幕上输出一个空格而已。简直和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 %eax
	movl $0x250,%eax
	pop %eax
	ret

    这个够简单,在3级用户代码里call example就可以调用了,没有输出提示所以我们可以通过bochs调试来确认,结果就是调用成功,执行过程成功进入此example代码。这就是个普通近调用,没啥特殊的。关于陷阱门特权级我们就说到这里。

    说完了。

本文出自 “mirage1993” 博客,请务必保留此出处http://mirage1993.blog.51cto.com/2709744/1576602

Linux0.00内核为什么要自己设置0x80号陷阱门来调用write_char过程?

标签:linux内核   陷阱门   0.00   

原文地址:http://mirage1993.blog.51cto.com/2709744/1576602

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!