linux解析任务堆栈方法,深度剖析Linux0.11系统中堆栈的使用方法

本文详细介绍了Linux0.11系统中堆栈的使用,包括系统引导初始化时的堆栈、保护模式后的内核堆栈、任务内核态堆栈和用户态堆栈。在不同特权级下,堆栈的切换和保护机制确保了系统的稳定运行。每个任务都有独立的内核态堆栈和用户态堆栈,内核态堆栈位于任务数据结构的末端,而用户态堆栈则在64MB地址空间的末端。堆栈管理是Linux内核设计的关键部分,确保了任务执行的高效和安全。
摘要由CSDN通过智能技术生成

在工作中关于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

*为什么从主存区申请得来的用于保存任务数据结构的一页内存也能被设置成内核数据段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值