所以我正在阅读MicroC / OS-II的书,但是在任务堆栈的部分我找不到堆栈的确切内容,最重要的是 - 它用于什么。我知道这不是漫长而艰难的事情,但我有点必须理解它。这本书只介绍了如何设置堆栈大小以及其他类似的东西。 那么,在uC / OS-II中,有人能用简短的单词向我解释什么是任务堆栈及其用途是什么?
答案 0 :(得分:3)
我不知道MicroC / OS-II,但任务的堆栈几乎总是相同的:
在执行任务期间,它存储当前上下文中所需的数据。这意味着当调用子程序(方法等)时,“堆栈帧”存储在堆栈的顶部。该堆栈帧存储被调用子例程的局部变量,子例程完成时使用的返回地址以及其他一些信息。子例程返回时,将删除堆栈帧。如果子例程调用另一个(或递归自身),则另一个堆栈帧存储在当前子堆栈的顶部
与存储数据以与存储数据相反的顺序删除的堆栈相反,只要存储器的内存未被释放,堆就会存储数据,这可以按任意顺序完成。
答案 1 :(得分:2)
通常在过程编程语言的上下文中,堆栈是存储函数/过程/子例程的局部变量和返回地址的位置(在“堆栈帧”中) - 调用深度越大,存储的堆栈帧就越多 - 每个函数尚未返回一个。无论您是否使用MicroC / OS-II等RTOS,该部分都是正确的。
在单线程环境中,只需要一个堆栈,这通常是作为C运行时环境设置的一部分为您提供的。在多线程环境中,每个单独的执行线程都需要一个堆栈,通常由您为每个线程分配堆栈空间,或者至少指定其长度。
答案 2 :(得分:2)
许多处理器都有一个堆栈指针,其中大多数都有专门使用该堆栈指针的指令。堆栈指针是一个保存地址的寄存器,与程序计数器不同。堆栈只是堆栈指针指向的内存,在更高级别你或操作系统或某人将可用内存空间划分为不同的用途,稍微为程序稍微为数据堆(mallocs和frees)还有一些用于堆栈。堆栈指针和相关指令允许代码临时分配一些内存。例如,一个全局变量至少是在一个内存位置停留的程序的生命周期。一个局部变量虽然在执行函数时只需要一个内存位置,但是当函数返回时你不需要那个局部变量内存(静态定义的本地分配像globals那样但只在该函数期间可用,所以不是临时的)。您可以在函数中执行malloc并释放以分配此本地内存,或者您可以简单地使用堆栈。许多/大多数编译器只使用堆栈。除了局部变量之外,您可能需要存储返回地址,如果函数a()调用函数b()从b返回到您所处的位置,则需要在调用b()之后返回到下一条指令。如果B调用c然后在b()的上下文中你需要将返回保存到(),现在在c()中你需要知道如何返回b()。等等。这是依赖于体系结构和调用约定的,一些体系结构总是使用堆栈进行返回,有些体系结构倾向于使用特定的寄存器。嵌套调用虽然所有架构都需要最终使用堆栈作为返回地址,因此这里也使用堆栈。如果函数a()调用自身10次并且有一个本地整数,并且返回地址让我们说它每次调用需要8个字节的堆栈,所以第一次调用移动堆栈指针8个字节分配8个字节,第二个调用另外8个等等。当你开始命中返回时,堆栈指针向后移动8个字节,另一个在堆栈指针上返回另外8个字节。
现在将其从单个应用程序转换为多个应用程序,如果同时为每个应用程序/任务/过程/线程执行(操作系统),或者您希望每个应用程序都拥有自己的堆栈。这通常很简单,因为您只需要保存先前任务中的堆栈指针,并将堆栈指针设置为切换时下一个任务的最后一个值。当然,您可以获得更复杂的保护机制,因此每个应用程序只能在其内存空间中生存,包括堆栈和堆。通过将物理内存切碎成许多部分,mmus可以使它变得更加复杂,并且mmu使得它看起来像应用程序虚拟地址空间中的单独部分是线性的。等
因为nurd_droid指出某些处理器具有不同的堆栈指针,具体取决于处理器的模式。您可能有一个用于用户/应用程序模式,然后当系统调用发生系统/超级用户堆栈指针,并且中断发生中断堆栈指针。有些架构只有一个堆栈指针...有些架构堆栈不在主存储器空间中,堆栈和堆栈指针都埋没在逻辑中而你真的没有看到它(通常在这种情况下堆栈大小非常有限并且可以如果您不管理堆栈使用情况,请自行处理或其他不好的事情。)
答案 3 :(得分:0)
Stack是一种后进先出(LIFO)类型的数据结构,过程语言使用它来执行推送/弹出本地变量,CPU寄存器,在进行函数调用之前返回地址,或者发生中断或准备上下文切换。
变量,寄存器以完全相反的顺序弹出,与它们被推入堆栈的顺序相比。
堆栈可以在内存中向上或向下增长。这取决于微控制器。
此外,许多微控制器都有多个堆栈。 1)用户堆栈 2)异常堆栈或中断堆栈
如果使用RTOS,那么每个进程/线程/任务都将拥有自己的堆栈。在这种情况下,用户SP微控制器寄存器将由上下文切换例程重新分配,以指向当前活动进程/线程/任务的堆栈。
异常堆栈或中断堆栈在整个系统中共享。