Linux 操作系统浅析

 

sa**373 陈彦宏

一 存储程序计算机、堆栈(函数调用堆栈)机制和中断机制

 

1、存储程序计算机的体系结构如图所示

CHENYANHONG

        根据结构图其主要流程分为四步:第一步:将程序和数据通过输入设备送入存储器;第二步:启动运行后,计算机从存储器中取出程序指令送到控制器去识别,分析该指令要求;第三步:控制器根据指令的含义发出相应的命令,将存储单元中存放的操作数据取出送往运算器进行运算,再把运算结果送回存储器指定的单元中;第四步:当运算任务完成后,就可以根据指令将结果通过输出设备输出。(参考百度)

2、堆栈(函数调用)

关于堆栈在函数调用中的机制在之前的博文中已有结合代码的分析http://blog.csdn.net/tvdlygh/article/details/8925768,关于函数的调用个人理解为是从一块代码到另一块代码之间的双向数据传递和执行控制,通过ESP堆栈顶指针和EBP堆栈基指针的变化来实现程序的执行过程,而在函数调用的过程中callret两条指令十分重要

call:把返回地址压入栈中并且跳转到调用函数开始处并且执行。
ret:调用ret之前要好好处理栈中的内容。使得当前栈指针所指向的位置刚好为call指令保存的返回地址。另外若函数返回一个整数或指针,那么用eax返回。

3、中断机制

       中断可以很简单的形容为cpu暂停目前正在处理的任务,转而去处理新的请求处理的任务,当新任务处理完成后,再回到原来暂停的位置,继续处理原有的任务。

          以下内容摘选自李春杰老师课件:

                         当执行了一条指令后,cseip这对寄存器包含了下一条将要执行的指令的逻辑地址。

                         在执行这条指令之前,CPU控制单元会检查在运行前一条指令时是否发生了一个中断或者异常。

                         如果发生了一个中断或异常,那么CPU控制单元执行下列操作:

                                                                                 1,确定与中断或者异常关联的向量i(0~255)

                                                                                 2,idtr寄存器指向的IDT表中的第i

                                                                                 3,gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的段选择符所标识的段描述符

                                                                                 4,确定中断是由授权的发生源发出的。

                                               中断:中断处理程序的特权不能低于引起中断的程序的特权(对应GDT表项中的DPL vs CS寄存器中的CPL)

                                                编程异常:还需比较CPL与对应IDT表项中的DPL

                                                                                 5,检查是否发生了特权级的变化,一般指是否由用户态进入了内核态。如果是由用户态进入了内核态,控制单元必须开始使用与新的特权级相关的堆栈

                                                                                  a,tr寄存器,访问运行进程的tss

                                                                                  b,用与新特权级相关的栈段和栈指针装载 ssesp寄存器。这些值可以在进程的tss段中找到

                                                                                  c,在新的栈中保存ssesp以前的值,这些值指明了与旧特权级相关的栈的逻辑地址

                                                                                 6,若发生的是故障,用引起异常的指令地址修改cseip寄存器的值,以使得这条指令在异常处理结束后能被再次执行

                                                                                 7,在栈中保存eflagscseip的内容

                                                                                 8,如果异常产生一个硬件出错码,则将它保存在栈中

                                                                                 9,装载cseip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量字段。相对对寄存器值给出中断或者异常处理程序的第一条指定的逻辑地址

中断/异常处理完后,相应的处理程序会执行一条iret汇编指令,这条汇编指令让CPU控制单元做如下事情:

                                  1,用保存在栈中的值装载cseipeflags寄存器。如果一个硬件出错码曾被压入栈中,那么弹出这个硬件出错码

                                  2,检查处理程序的特权级是否等于cs中最低两位的值(这意味着进程在被中断的时候是运行在内核态还是用户态)。若是,iret终止执行;否则, 转入3

                                  3,从栈中装载ssesp寄存器。这步意味着返回到与旧特权级相关的栈

                                  4,检查dsesfsgs段寄存器的内容,如果其中一个寄存器包含的选择符是一个段描述符,并且特权级比当前特权级高,则清除相应的寄存器。这么做是防止怀有恶意的用户程序利用这些寄存器访问内核空间

 

自己做了个框架图:

二 操作系统(内核)是如何工作

例如,当一个进程在执行一个程序的时候,进来一个中断,CPU首先将当前EIP,ESP压入内核栈,然后把ESP指向内核栈,EIP指向中断处理的入口,其中最关键的就是TSS,因为TSS中保存了用户态下各个寄存器的信息,所以将用户态下的EIP和ESP入栈,就相当于对进程之前的一个状态进行保存,以便于从中断返回后继续执行之前任务,然后kernel调用SAVE_ALL来将其他寄存器信息保存在栈中,接着根据CS EIP指向的中断程序,对中断进行处理。当执行完一个中断后,会通过schedule进行调度,其中最重要的要数switch_to,其会调用_switch_to函数来进行调度。当中断执行完后,若要返回到用户态,就需要回到最初中断开始的地方继续执行先前任务,这就需要restore_all将之前保存在内核栈中的值出栈,然后通过iret恢复其计算器的状态,这样我们就又回到了用户态,继续执行之前因中断而暂停的任务。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值