2016-08-19 103 views
1

在Keil RTX RTOS配置文件中,用户可以配置默认的用户线程堆栈大小。 通常,堆栈包含自动/本地变量。 “ZI数据”部分保存未初始化的全局变量。Keil RTX RTOS线程堆栈大小

因此,如果我更改RTX配置文件中的用户线程堆栈大小,堆栈大小将增加,并且“ZI数据”节大小不会增加。

我测试一下,测试结果显示如果我增加用户线程堆栈大小。 “ZI数据”部分的大小将以相同大小同步增加。

在我的测试程序中,有6个线程,每个线程有600个字节的堆栈。我使用Keil来构建程序,它告诉我:

 
     Code (inc. data) RO Data RW Data ZI Data  Debug 

    36810  4052  1226  380  6484  518461 Grand Totals 
    36810  4052  1226  132  6484  518461 ELF Image Totals (compressed) 
    36810  4052  1226  132   0   0 ROM Totals 

============================================================================== 

    Total RO Size (Code + RO Data)    38036 ( 37.14kB) 
    Total RW Size (RW Data + ZI Data)    6864 ( 6.70kB) 
    Total ROM Size (Code + RO Data + RW Data)  38168 ( 37.27kB) 

但是,如果我将每个线程堆栈大小更改为800字节。 Keil显示如下:

 
============================================================================== 


     Code (inc. data) RO Data RW Data ZI Data  Debug 

    36810  4052  1226  380  7684  518461 Grand Totals 
    36810  4052  1226  132  7684  518461 ELF Image Totals (compressed) 
    36810  4052  1226  132   0   0 ROM Totals 

============================================================================== 

    Total RO Size (Code + RO Data)    38036 ( 37.14kB) 
    Total RW Size (RW Data + ZI Data)    8064 ( 7.88kB) 
    Total ROM Size (Code + RO Data + RW Data)  38168 ( 37.27kB) 

============================================================================== 

“ZI数据”部分的大小从6484增加到7684字节。 7684 - 6484 = 1200 = 6 * 200和800 - 600 = 200。 所以我看到线程堆栈放在“ZI数据”部分。

我的问题是: 这是否意味着汽车/在线程局部变量将被放置在“ZI数据”部分,当线程栈放在“ZI数据”一节中RAM? 如果这是真的,那意味着根本没有堆叠部分。根本只有“RO/RW/ZI数据”和堆段。

这篇文章给了我不同的答案。我现在对此有点困惑。 https://developer.mbed.org/handbook/RTOS-Memory-Model

+0

_“堆栈保存自动/本地变量”_ - 从正在运行的线程的角度来看,当然是“该”堆栈。尽管如此,我没有理由认为这些堆栈不能从操作系统的角度来看是静态分配的变量。你只是在这里提出一个观察;具体的问题是什么? – Notlikethat

回答

1

链接器确定存在哪些内存段。链接器默认创建一些内存段。在您的情况下,其中三个默认部分显然被命名为“RO数据”,“RW数据”和“ZI数据”。如果您没有明确指定变量应该位于哪个部分,则链接器将根据变量是否声明为const,初始化或未初始化将它分配给这些默认部分之一。

链接器不会自动意识到您正在使用RTOS。并且它没有关于你打算用作线程堆栈的变量的专门知识。所以链接器不会为你的线程堆栈自动创建独立的内存段。相反,链接器会像处理任何其他变量一样处理堆栈变量,并将它们包含在其中一个缺省内存段中。在你的情况下,线程堆栈显然被链接器放入ZI Data部分。

如果您希望链接器为您的线程堆栈创建特殊的独立内存段,那么您必须通过链接器命令文件明确告诉链接器。然后您还必须指定堆栈变量应该位于您的自定义部分中。有关如何执行此操作的详细信息,请参阅链接器手册。

+0

谢谢。通常有一些缺省部分:“RO数据”,“RW数据”和“ZI数据”,“堆栈”,“堆”。链接器确定闪存和RAM内存布局。如果将线程堆栈放入“ZI Data”中,是否表示线程中调用的所有函数的自动变量将位于“ZI Data”部分?那么在“堆栈”部分有什么? –

+0

主程序有一个堆栈。这是当调用main()时以及在RTOS启动之前正在使用的堆栈。您的链接器命令文件可以为主堆栈显式指定一个内存部分。每个线程都有独立于主堆栈的堆栈。您的链接器正在ZI Data部分找到这些线程堆栈。一旦RTOS正在运行,将在线程堆栈上创建线程局部变量。是的,线程局部变量将位于ZI Data中,因为线程堆栈位于ZI Data中。主栈是RTOS运行之前本地变量的位置。 – kkrambo

+0

RTOS运行后,“主函数”永远不会再被调用。所以一旦RTOS破坏,主堆栈就不会被使用。为了节省内存,这意味着主堆栈和线程堆栈的内存空间将被重叠。 –

0

任务堆栈必须来自某个地方 - 默认情况下,RTX会静态分配并且大小固定。

os_tsk_create_user()允许调用者提供可以以任何方式分配的堆栈(静态地或从堆中分配;从调用者堆栈分配是可能的,但是不寻常的,可能毫无意义且当然是危险的),只要它具有8字节对齐。我发现RTX的自动堆栈分配几乎没有用,除了最琐碎的应用程序之外几乎都不适用。