Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1134998
  • 博文数量: 414
  • 博客积分: 10030
  • 博客等级: 上将
  • 技术积分: 4440
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-05 21:42
文章分类

全部博文(414)

文章存档

2011年(1)

2009年(1)

2008年(412)

我的朋友

分类: LINUX

2008-10-11 08:38:30

主要结构是高层的用户程序,然后是一些,lib函数库啊,然后是系统调用,用户可以通过一个系统调用陷入到内核中去,将进程进入内核态中运行,享用内核提供的超级NB的诸如进程调度,信号啊等操作,接着就是一些对硬件资源的了。

了解了内核的结构后,我们接下来要知道内核都干了什么事情啊!

首先,最基本的启动OS,创建进程,创建完进程后,要对进程管理啊,又有了进程调度,那轻进程呢,系统呢,I/O设备,中断,虚拟内存的管理呢,这些都是内核一个人干的,很NB

再来了解下堆栈,大家对C中的堆栈应该都不陌生,它记录C中函数调用和参数,可以传递参数,保存,提供局部变量的空间等等。那具体的堆栈的细节部分呢?

EBP:堆栈基址指针,指向这个堆栈的基址位置,也就是堆栈栈底的位置

ESP:堆栈指针,总是指向栈顶

EIP:指向当前指令的地址,如果不好理解的话,可以理解为执行程序时的指向当前语句的位置。注意,仅仅是可以这么理解。

X86结构中堆栈的存放总是从高地址到低地址的,也就是说当你执行PUSH时,你的ESP会减少4个字节的,此时的ESP-=4,而你POP下的话,ESP会增加4个字节的,此时的ESP+=4

再说EIP,顺序执行时它总是指向地址连续的下一条指令。当发生JMP时指向JMP到的位置。你又想CALL下呢,它就会先将当前指令的顺序下一条指令压入栈顶,然后调到被调用函数的入口地址,等该函数执行完事了,它在从栈顶POP出原EIP,接着继续执行,这就是RET干的事情。那么中断呢,我会在后面说到。

下面从堆栈的角度说下CALL这个过程:

当执行到CALL时,此时会将当前EIP的下一条指令的地址压到栈顶,然后EIP变成是被调用的函数的入口地址。

接着要构建新的被调用函数的框架,首先是先把当前的EBP压到栈顶(这是为了以后RET做的准备),接着把ESP赋给EBP,也就是说新的堆栈基址EBP是指向它原来EBP保存的地址上的(晕了没,J),接着执行新的函数,此时会伴随着压栈,出栈,ESP在不断变化。此时的汇编语句是:pushl %ebpmovl %esp, %ebp

被调用的函数执行完事后,此时要讲为它构建的堆栈撤消掉,先要让ESP指向当前EBP的位置上(这一个简单的操作就把被调用的函数的栈体给抛弃了),然后POP出原来的EBP,这样EBP又重新指回到自己原来的位置上去,而且ESP也指到了自己原来的位置上。至此被调用的函数的临时栈撤消完毕。该过程的汇编语句是:movl %ebp,%esppopl %ebp

最后要返回到原来EIP的下一条指令来执行啊,怎么办,此时只要POP下就可以,这样和先前的工作呼应起来了吧。

大家可以写几个很简单小程序,然后用Objdump –s反汇编出目标文件的汇编文件,如果你去查看,会得到我上面说的结果。

用户态和内核态

X86结构体系中提供了四种不同的状态,但所有的UNIX内核都只使用了其中的两种,那就是内核态和用户态。正常进程执行的过程是先在用户态里面玩,然后发生系统调用时陷入到内核态,然后直到发生定时中断且调度程序在内核态被激活(这就是后面要讲到的时间片轮转和进程调度)进程才恢复到用户态执行。

激活内核态的方式有:

系统调用

正在执行的CPU发出异常信号。

外围设备向CPU发出一个中断信号通知事件的发生

内核线程被执行

当用户态陷入到内核态时必须保存用户态寄存器的上下文,中断/int指令会在堆栈上保存一些寄存器的值,如:用户态栈顶地址、当时的状态字、当时的cs:eip的值。也是因为这些原因,pt_rags应运而生了。

阅读(447) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~