您的位置 首页 制造

学会Linux0.11-体系中仓库的使用方法

学会Linux0.11-系统中堆栈的使用方法-当bootsect代码被ROM BIOS引导加载到物理内存0x7c00处时,并没有设置堆栈段,程序也没有使用堆栈,直到bootsect被移动到0x9000:0处时,才把堆栈段寄存器SS设置为0x9000,堆栈指针esp寄存器设置为0xff00,所以堆栈堆栈在0x9000:0xff00处(boot/bootsect.s L61,62)setup.s也使用这个堆栈

在工作中关于 Linux体系中的仓库问题一向是工程师们很头疼的问题,特别呈现一些新的版别,下面就与我们一同同享以下 Linux0.11 体系中仓库的运用方法。

一、体系引导初始化暂时运用的仓库。

二、进入维护形式后供给内核程序始化运用的仓库,该仓库也是后来使命0运用的用户态仓库。

三、每个使命经过体系调用,履行内核程序时运用的仓库,称之为使命的内核态仓库,每个使命都有自己独立的内核态仓库。

四、使命在用户态履行的仓库,坐落使命(进程 )逻辑地址空间近结尾处。

运用多个栈或在不同情况下运用不同栈的首要原因

首要,因为从实形式进入维护形式,使得CPU对内存寻址拜访方法发生了改变,因而需求从头设置仓库区域;其次,为了处理不同CPU特权级同享运用仓库带来的维护问题,履行0级的内核代码和履行3级的用户代码需求运用不同的栈。当一个使命进入内核态运行时,就会运用其TSS段中给出的特权级0的仓库指针tss.ss0.tss.esp0,即内核栈,原用户栈指针会保存在内核栈中,而当从内核态回来用户态时,就会康复运用用户态的仓库。

以下别离阐明。

开机初始化时(bootsect.s,setup.s)

当bootsect代码被ROM BIOS引导加载到物理内存0x7c00处时,并没有设置仓库段,程序也没有运用仓库,直到bootsect被移动到0x9000:0处时,才把仓库段寄存器SS设置为0x9000,仓库指针esp寄存器设置为0xff00,所以仓库仓库在0x9000:0xff00处(boot/bootsect.s L61,62)setup.s也运用这个仓库

进入维护形式时分(head.s,L31)

此刻仓库段被设置为内核数据段(0x10),仓库指针esp设置成指向user_stack数组(sched.c L67~72)的顶端,保留了1页内存作为仓库运用。

初始化时(main.c)

在履行move_to_user_mode()代码把控制权移交给使命0之前,体系一向运用上述仓库,而在履行过move_to_user_mode()之后,main.c的代码被“切换”成使命0中履行。经过履行fork()体系调用,main.c中的init()将在使命1中履行,并运用使命1的仓库,而main()自身则在被“切换”成为使命0后,仍热持续运用上述内核程序自己的仓库作为使命0的用户态仓库。

使命的仓库

每个使命都有两个仓库,别离用于用户态和内核态程序的履行,而且别离称为用户态仓库和内核态仓库。

除了处于不同CPU特权级中,这两个仓库之间的首要差异在于使命的内核态仓库很小,所保存的数据最多不能超过4096个字节,而使命的用户态仓库却能够在用户的64MB空间中延伸在用户态运行时每个使命(除了使命0和使命1)有自己的64MB地址空间,当一个使命(进程)刚被创立时,它的用户态仓库指针被设置在其地址空间的接近结尾部分,应用程序在用户态下运行时就一向运用这个仓库,实践物理地址内存则由CPU分页机制确认。

在内核态运行时

每个使命有其自己的内核态仓库,用于使命在内核代码中履行期间。其地点的线性地址中方位由该使命TSS段中ss0和esp0两个字段指定,使命内核态仓库被设置在坐落其使命数据结构地点页面的结尾,即于使命的使命数据结构(task_struct)放在同一页面中,拜见kernel/fork.c L93

p->tss.esp0 = PAGE_SIZE + (long)p;

p->tss.ss0 = 0x10

*为什么从主存区请求得来的用于保存使命数据结构的一页内存也能被设置成内核数据段中的数据呢?便是说tss.ss0为什么能够是0x10?

用户内核态依然归于内核数据空间,在head.s中设置内核代码段和数据段的描述符,段长度都设置成了16MB,这个长度值是Linux0.11内核所能支撑的最大物理内存长度(head.s,110开端的注释),所以,内核代码能够寻址到整个物理内存规模中的任何方位,当然也包含主存区,每逢使命履行内核程序而需求运用其内核栈时,CPU就会运用TSS结构把它的内核态仓库设置成由tss.ss0和tss.esp0这两个值构成使命0(闲暇进程idle)和使命1(初始化进程init)的仓库使命0和使命1的代码段和数据段相同,限长都是640KB,但它们被映射到不同的线性地址空间,使命0的段基址从线性地址0开端,而使命1的段基址从64MB开端,但他们悉数映射到物理地址0~640KB规模中,这个地址也便是内核代码和根本数据所寄存的当地,在履行了move_to_user_mode()后,使命0和使命1的内核态仓库别离坐落各自使命数据结构地点页面的结尾,而使命0的用户态仓库便是前面进入维护形式后运用的仓库,即user_stack[]数组的方位,因为使命1在创立时仿制了使命0的用户仓库,所以刚开端时使命0和使命1同享运用同一个用户仓库空间,可是当使命1开端运行时,写时仿制机制会为使命1另行分配主存区页面作为仓库空间运用,只要到这个时分,使命1才开端运用自己独立的用户仓库内存页面,因而使命0的仓库需求在使命1实践开端运用之前坚持洁净,即使命0此刻不能运用仓库,以保证仿制的仓库页面中不含使命0的数据。

 

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/zhizao/99915.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部