gzyueqian
13352868059

嵌入式培训学什么内容?有关嵌入式系统之堆和栈的理解

更新时间: 2019-03-20 14:21:16来源: 嵌入式培训浏览量:4791

  嵌入式培训内容会涉及到堆(heap)和栈(stack),它们是嵌入式系统中非常重要的概念,特别是当我们要进行嵌入式系统程序开发时得深入去理解堆和栈的定义。

  在嵌入式系统中,任务的栈通常都很小,可能也就几K字节。在这种情况下,我们就应当尽可能不要将占用内存大的变量分配在栈上,而是应当分配在堆上;此外,也尽量不要采用递归的方式来设计程序,否则很容易造成栈溢出。

  从本质上说,堆和栈都是内存,那么我们只能从嵌入式培训内容概念上对其进行区分了。为了方便说明,现在假设嵌入式软件是一个单体程序和我们的应用程序是被编译在同一个可执行程序当中的,比如,来自WindRiver的VxWorks就是采用这种方式的。我们知道一个可执行程序存在为重要的三个段。.text段用于存放程序的代码,即放的是处理器的运行指令。.data用于存放初始化好的数据,当boot loader加载程序文件时,会将程序文件中的.data段拷贝到内存的VMA(Virtual Memory Address)处,从而完成变量的初始化操作。虽然,我们在C/C++程序中是对全局变量一个一个初始化的,但实际上boot loader是对所有的全局变量通过将程序文件中的.data段拷贝到内存中一次性的完成初始化的。.bss段用于存放没有初始化好的变量,程序文件中并不存放.bss段的具体内容,只是存有.bss段的起始地址和大小,当boot loader加载我们的嵌入式程序文件时,只是根据程序文件中的.bss信息对内存中的.bss块进行清零操作。

  堆我们说过了,那接下来我们看一看如果我们的单体程序继续运行,会出现什么样的内存布局。我们知道,通常我们的单体程序在初始化时往往需要创建多个任务来实现其应用功能。对于每一个任务,它一块内存是私有的,那就是栈!当任务运行时,其需要用栈来做为函数调用时的参数传递空间,以及用栈来存储函数内的局部变量。假设我们的单体程序需要创建两个任务A和B,这需要通过调用操作系统中的任务创建函数来达到这一目的。操作系统所提供的任务创建API往往需要我们指定任务栈的大小,有的甚至可以指定栈内存空间。一旦任务创建的API被调用,那么操作系统会调用堆分配API为任务分配栈。

  对于堆我们已经知道了必须调用相应的API来分配内存,那从栈空间分配内存也需要调用API吗?答案是通常不需要,为什么是通常?因为,在有的平台上(Linux上就是)提供栈空间的分配API,即这种API被调用时,是从调用任务的栈空间中分配内存的。对于这一功能,在嵌入式系统中使用得非常的少,粤嵌嵌入式培训不建议大家使用。对于下面的代码,mem_main、mem_foo和mem_bar的大小是4K字节(假设int类型的大小是4字节),这些内存就是自动(注意是自动)分配在运行任务的栈上的。我们假设某个任务当前所使用的栈是零字节,当这一任务运行到main中且没有进入foo ()时,其所占用的空间大小是大约4K字节,之所以用大约这个词,是因为函数的调用还有其它的栈开销。一旦任务运行进入foo ()函数但没有进入bar ()函数,那么所占用的栈的大小就变为大约8K字节。同样的,如果程序运行进入bar ()函数,那么所占用的栈空间大约就是12K字节了。

  void bar ()

  {

  int mem_bar [1024];

  // application logic

  }

  void foo ()

  {

  int mem_foo [1024];

  bar ();

  }

  int main ()

  {

  int mem_main [1024];

  foo ();

  return 0;

  }

  如果程序继续运行,从bar ()函数返回到foo ()函数中,那么其所占用的栈空间就从大约12K字节变成了大约8K字节了。相类似的是,如果程序从foo ()函数中返回到main ()函数,那么所占用的栈空间又变为大约4K字节了。对于嵌入式系统开发,由于任务栈通常都比较的小,那这告诉我们什么呢?我想有以下几点需要注意。

  1)函数的调用深度越是深,由于每一级的函数通常都会有局部变量,那么所使用的栈空间也会累积得越大。

  2)递归调用需要的栈空间会相对的大(视具体的情况),在嵌入式系统中也建议少用。

  3)我们应当尽可能的不要在函数中定义占用内存空间较大的局部变量。

  下面,我们总结一下堆与栈的区别,它们是:

  1)堆是大家共享的。任务可以通过调用API来从堆中分配内存空间。

  2)栈是任务所独有的。在嵌入式系统开发中,当一个任务创建起来后其栈空间的大小往往是定了的。函数中的局部变量是由编程语言自动从栈上分配的,我们不需要调用API进行空间分配。

  关于嵌入式培训内容中堆和栈的理解就先说到这里,如果你对嵌入式感兴趣,到粤嵌培训会是一条不错的出路。


免费预约试听课