学号:sg***5028,姓名:王群峰
基础知识
“存储程序”原理,是将根据特定问题编写的程序存放在计算机存储器中,然后按存储器中的存储程序的首地址执行程序的第一条指令,以后就按照该程序的规定顺序执行其他指令,直至程序结束执行。
存储程序和程序控制原理的要点是,程序输入到计算机中,存储在内存储器中(存储原理),在运行时,控制器按地址顺序取出存放在内存储器中的指令(按地址顺序访问指令),然后分析指令,执行指令的功能,遇到转移指令时,则转移到转移地址,再按地址顺序访问指令(程序控制)。
以上参考资料:http://baike.baidu.com/view/2083958.htm
Linux/x86中的函数调用堆栈
C程序中各个函数之间的调用借助堆栈来完成。在x86体系结构中,采用满递减型栈结构。堆栈相关的两个重要的寄存器分别是:
Esp:栈顶指针 和 ebp: 栈底指针。二者分别指向栈顶和栈底,中间标记的一段存储区域为栈。
如果一个函数在执行过程中可能会调用到其他函数并且需要向它所调用的函数传递参数,那么在caller刚开始建立自身的栈的时候,就会把栈扩大预留出一段内存用来将来传递这些参数;
如果函数内部有自动变量,那么也会在刚开始建立自身栈的时候把栈扩大一些,预留出空间来存放这些变量。
这时执行的指令是sub $0x**,%esp
当发生函数调用时执行以下几个步骤(或只执行其中一部分):
1.将caller提供的实参mov到靠近栈顶处的预留空间;
2.执行call指令,该指令将CS:EIP寄存器的内容压入到当前栈中;
3.进入callee子函数,把原来的esp的内容写入到ebp中,esp继续向下,如果把整个栈区看作是多个函数的栈的组合的话,那么此处可以认为是在更换一个新的栈
4.在callee子函数中,当需要用到caller传递过来的参数时,将按照ebp作为基址加上一个正的偏移量来访问
5.当函数返回时,如果有返回值,通常会将返回值存放到eax寄存器中,并执行leave 和 ret指令。Leave指令用来切换回caller的栈,ret指令用来恢复CS:EIP
分析时所参考的程序如下图所示:
中断机制
中断是一个操作系统的核心,操作系统之所以能够进行进程调度,最关键的因素之一就是中断机制的存在。
在包括Linux在内的众多操作系统中,最基本的中断是时钟中断,时钟中断是内核的心脏,正是在时钟中断的驱动下,内核才可以相对稳定地周期性的管理、调度应用程序,管理存储器、管理I/O操作等等。
在Linux中,中断程序的执行仅限于在内核态,用户态无法触及中断这种底层的操作。
中断服务程序的执行是处在进程上下文的,中断服务程序执行时,总是屏蔽掉相应的中断的,这样,中断服务程序执行的时间长短就影响了CPU的性能。
鉴于此,在linux内核中,中断的处理被分为上半部和下半部两部分。其中,上半部主要用来完成一些时间要求极为苛刻的、必须处理的操作;下半部则用来实现一些可以稍后推迟,但总体优先级要高于普通进程的一些处理工作。
中断执行的末尾,会设置一些标志,以表明和它相对应的某个下半部程序需要被调度执行。中断下半部执行时,CPU会打开中断线,允许接受并处理一些中断。
内核基本原理介绍(自己理解,仅供参考)
内核直接工作在cpu之上,为用户程序提供一个可运行的软件环境,以及一些共享库、静态库、系统软件工具等。
Linux内核提供了进程管理、内存管理、文件系统、网络管理、IO设备管理等强大的功能。
内核最核心的工作是进程管理。处理器是计算机系统中最重要的资源。在现代计算机系统中,为了提高系统的资源利用率,CPU将为某一程序独占。通常采用多道程序设计技术,即允许多个程序同时进入计算机系统的内存并运行!
上段内容参考:http://baike.baidu.com/view/364947.htm#1
进程管理中,最重要的管理就是进程切换,即在不同时刻,将不同的进程投入CPU运行。内核的工作主要包括:任务调度算法、任务调度时机、任务优先级的分配与动态改变、任务类型划分(实时进程与非实时进程)等。
进程的切换是由内核执行的,进程切换的动作一般发生在中断处理函数中,在进程切换过程中,有如下的函数/宏调用关系:
Schedule()-->__schedule()-->context_switch()-->switch_to-->__switch_to()
Schedule()和__schedule()函数中主要是确定是否需要进行进程切换,以及具体从哪一个进程切换到哪一个另外的进程。
Context_switch()函数完成上下文的切换,主要是切换到新的内存描述符以及新的线程寄存器状态。
Switch_to是一个宏,它调用__switch_to()用来切换进程的堆栈为next进程的堆栈。因为在内核态中,栈顶指针减去8K偏移即可得到thread_info的位置,【参考:http://www.cnblogs.com/sunshinewill/archive/2013/03/05/2943872.html】因此后面可以据此修改current宏为新的进程。
最后,调度程序退出,新的进程开始投入运行。