软件调试笔记30 - 栈和函数调用 : 栈简介

本文详细介绍了在计算机科学中栈的概念及其应用。从数据结构的角度出发,解释了栈的后入先出特性,以及编译器如何将函数调用转换为栈操作。此外,还探讨了操作系统如何为线程创建和管理栈,特别是用户态栈和内核态栈的区别。

简介

从数据结构,栈是一种用来存储数据的容器,遵从后入先出规则。 编译器在编译时会将函数调用和局部变量存取编译为合适的栈操作。操作系统在创建线程时,会为每个线程创建栈,包括分配栈所需的内存空间和初始化有关的数据结构及寄存器。以x86为例,SS(stack segment)寄存器用来描述栈所在的内存段,ESP(extended stack pointer)寄存器用来记录栈的栈顶地址。CPU在执行程序时,会假定SS和ESP已经指向一个设置好的栈,执行PUSH指令就向ESP所指向的内存地址写入数据,然后调整ESP值,使其指向新的栈顶。执行POP就弹出数据,并调整ESP的值。当CPU执行CALL和RET这样的函数调用指令时,也会使用栈。


从线程角度,栈是每个WINDOWS线程必备的设施。每个线程至少有一个栈,系统线程之外的每个线程有两个栈,一个供该线程在用户态在执行使用-用户态栈,一个在内核态下执行使用,称为内核态栈。在一个多任务的系统中,会有多个线程,所以有很多个栈存在。但对CPU而言,它只使用当前栈,即SS和ESP所指向的栈。当在不同任务切换,以及同一个任务内核态和用户态切换,系统会保证SS和ESP始终指向合适的栈。


用户态栈和内核态栈






WINDOWS会为系统内的普通线程建立一个共享的TSS段,当进行软件方式的任务切换时,WINDOWS会把当前任务的内核态信息复制到TSS段。


用户态栈的信息记录在线程信息块_NT_TIB结构中,它是线程环境块TEB结构的第一部分,因此可以根据TEB地址来显示它。



从功能和使用方式看,用户态栈和内核态栈是相同的。但因为服务对象不同,所以还是有差异的。

1. 首先, 用户态栈是分配在所在线程的用户空间中,而内核态栈是系统空间。而用户空间是共享的,系统空间是全局的。一个系统内用户空间有很多个,但系统空间只有一个。

2. 用户态栈是可指定大小的,默认是1MB,而内核态栈是系统来控制大小的,大小因处理器结构不同而不同,但通常在十几KB到几十KB之间。在一个线程被转变为GUI线程后(创建的时候,所有线程都是非GUI线程),WINDOWS会为他创建一个较大的可增长的内核态栈来替换掉原来的栈,称为大内核态栈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值