SylixOS线程堆栈大小浅析

目录

1. SylixOS线程、线程栈介绍    1

1.1    线程的介绍    1

1.2    线程栈的介绍    1

2. SylixOS线程栈大小的分配    1

2.1    线程、线程栈相关属性的设置    2

2.2    线程栈大小    2

2.3    线程堆栈警戒区    3

3. 总结    5

4. 参考资料    5

  1. SylixOS线程、线程栈介绍

    SylixOS是多线程操作系统,系统能够同时创建多个线程,具体最大线程数量取决于系统内存的大小以及编译SylixOS操作系统时的相关配置,SylixOS线程默认最大线程数量由宏LW_CFG_MAX_THREADS决定,该宏定义可以在文件<config/kernel/kernel_cfg.h>中发现。

  2. 线程的介绍

    线程有时被称为轻量级进程(Lightweight Process,LWP),在SylixOS中线程又被称为任务,是某个单一顺序的指令流,也是操作系统调度的最小单位,并且每个线程都拥有自己的优先级。一个线程通常由线程句柄(或ID)、当前指令(PC)、CPU寄存器集合、线程栈四个部分组成。

  3. 线程栈的介绍

    每个线程都有自己独立的栈区,每一个线程控制块保存了栈区的起始位置、终止位置、以及栈警戒点(用于栈溢出检查)。当发生任务调度是,线程栈区将保存线程的当前环境(用于上下文恢复)。因此线程栈的设置必须合理,太大将浪费内存空间,太小可能会引起栈溢出。SylixOS中所有的线程都是在同一页表中,为了满足实时性要求线程之间没有地址保护机制,因此栈溢出将可能导致系统崩溃等不可预知的结果。

  4. SylixOS线程栈大小的分配

    每一个SylixOS线程都有自己的属性,主要包括优先级、栈信息、线程参数等。这在线程创建时,SylixOS提供了一个快速获得系统默认属性块的函数Lw_ThreadAttr_GetDefault。该函数返回值是线程属性块,默认线程大小为4K(正常通过shell命令运行程序时,程序继承的是shell的栈)。SylixOS可以使用相关的API函数对线程栈做出相应修改,如表 21所示是一些与线程堆栈相关的API函数。

    表 21  线程堆栈相关的API函数


    API接口


    功能描述


    pthread_attr_init


    初始化线程属性块


    pthread_attr_destroy


    销毁一个线程属性块


    pthread_attr_setstack


    设置堆栈的相关参数


    pthread_attr_getstack


    获得堆栈的相关参数


    pthread_attr_setguardsize


    设置一个线程属性块的堆栈警戒区大小


    pthread_attr_getguardsize


    获取一个线程属性块的堆栈警戒区大小


    pthread_attr_setstacksize


    设置一个线程属性块的堆栈大小


    pthread_attr_getstacksize


    获取一个线程属性块的堆栈大小


    pthread_attr_setstackaddr


    指定一个线程属性块的堆栈地址


    pthread_attr_getstackaddr


    获取一个线程属性块的堆栈地址


    pthread_attr_setstackfilled


    设置线程属性块栈填充特性


    pthread_attr_getstackfilled


    获得线程属性块栈填充特性


    ……


    ……

  5. 线程、线程栈相关属性的设置

    SylixOS提供下面一组函数来对线程的属性块参数进行设置,如程序清单 21所示:

    程序清单 21  线程属性块


    /*********************************************************************************************************

    线程属性块

    *********************************************************************************************************/

    typedefstruct {

    PLW_STACKTHREADATTR_pstkLowAddr;                   /*  全部堆栈区低内存起始地址    */

    size_tTHREADATTR_stGuardSize;                    /*  堆栈警戒区大小              */

    size_tTHREADATTR_stStackByteSize;                 /*  全部堆栈区大小(字节)        */

    UINT8THREADATTR_ucPriority;                      /*  线程优先级                  */

    ULONGTHREADATTR_ulOption;                       /*  任务选项                    */

    PVOIDTHREADATTR_pvArg;                        /*  线程参数                    */

    PVOIDTHREADATTR_pvExt;                        /*  扩展数据段指针              */

    } LW_CLASS_THREADATTR;

    typedefLW_CLASS_THREADATTR     *PLW_CLASS_THREADATTR;

  6. 线程栈大小

    栈大小的设置没有可以套用的公式,通常根据开发者经验设置一个较大的值,用存储空间换取可靠性。在正常进程启动情况下,会继承内核线程栈大小。如果创建线程是不设置线程栈属性,将会继承内核Shell线程的栈大小。如程序清单 22所示:

    程序清单 22  堆栈大小的函数


    intpthread_attr_setstacksize (pthread_attr_t  *pattr, size_tstSize)

    通过shell指令ss可以查看栈的大小,如图 21所示:

    图 21  shell指令查看栈大小

  7. 线程堆栈警戒区

    因为我们无法确定所需使用栈区的实际大小,我们通过设置堆栈警戒区的方式来防止堆栈溢出,系统设置默认的警戒区大小为1k,当出现堆栈溢出的状况时,系统会预警,如程序清单 23所示:

    程序清单 23  堆栈警戒区函数


    intpthread_attr_setguardsize (pthread_attr_t  *pattr, size_tstGuard)

    该函数对线程属性块的警戒区大小进行修改,参数stGuard指定新的栈警戒区栈大小。我们通过程序清单 23做一个详细了解:

    程序清单 23  堆栈溢出示例程序


    #include<stdio.h>

    #include<pthread.h>

    #include<time.h>

    void *routine(void *arg) {

    fprintf(stdout, "pthread running...\n");

    while(1);

    return (NULL);

    }

    intmain(intargc, char *argv[]) {

    pthread_ttid;

    pthread_attr_tattr;

    intret;

    ret = pthread_attr_init(&attr);

    if (ret != 0) {

    fprintf(stderr, "pthreadattrinit failed.\n");

    return (-1);

    }

    ret = pthread_create(&tid, &attr, routine, NULL);

    if (ret != 0) {

    fprintf(stderr, "pthread create failed.\n");

    return (-1);

    }

    pthread_join(tid, NULL);

    pthread_attr_destroy(&attr);

    return (0);

    }

    通过shell指令shstack(显示或者设置shell    任务堆栈大小)设置堆栈大小,再查看是否修改成功,然后运行程序,如图 22所示线程kl栈溢出:

    图 22  shell任务堆栈大小

    再通过ss 查看系统中所有线程与中断系统堆栈使用情况,如图 23所示:

    图 23 系统中所有线程与中断系统堆栈使用情况

    我们SylixOS的每个线程都有自己独立的栈区,对应的线程控制块保存了该栈区的起始位置、终止位置、以及栈警戒点(用于栈溢出检查)。在系统提供默认的属性块中,栈大小为4k,警戒区大小为1k,用户也可以根据自己的需求,通过相关的API函数来对栈的大小进行设置。

    《SylixOS应用程序开发手册》

    1. 参考资料

    2. 总结

时间: 2024-10-27 08:13:13

SylixOS线程堆栈大小浅析的相关文章

线程堆栈大小的使用介绍

先来讲说线程内存相关的东西,主要有下面几条: 进程中的所有的线程共享相同的地址空间. 任何声明为 static/extern 的变量或者堆变量可以被进程内所有的线程读写. 一个线程真正拥有的唯一私有储存是处理器寄存器. 线程栈可以通过暴露栈地址的方式与其它线程进行共享. 有大数据量处理的应用中,有时我们有必要在栈空间分配一个大的内存块或者要分配很多小的内存块,但是线程的栈空间的最大值在线程创建的时候就已经定下来了,如果栈的大小超过个了个值,系统将访问未授权的内存块,毫无疑问,再来的肯定是一个段错

线程堆栈大小 pthread_attr_setstacksize 的使用

pthread_create 创建线程时,若不指定分配堆栈大小,系统会分配默认值,查看默认值方法如下: # ulimit -s8192# 上述表示为8M:单位为KB. 也可以通过# ulimit -a 其中 stack size 项也表示堆栈大小.ulimit -s  value 用来重新设置stack 大小. 一般来说 默认堆栈大小为 8388608; 堆栈最小为 16384 . 单位为字节. 堆栈最小值定义为 PTHREAD_STACK_MIN ,包含#include <limits.h>

SylixOS线程私有数据浅析

目录 1. 线程私有数据概述    1 2. 线程私有数据的相关API函数流程浅析    1 2.1    加入线程私有变量    1 2.2    删除线程私有变量    3 2.3    设置私有线程变量    6 2.4    获得线程私有变量值    8 3. 总结    10 4. 参考文献    10 线程私有数据概述 在SylixOS中为了满足多线程安全的要求,使得一种资源可以安全的被多个线程使用,采用了包括代码临界区保护和可重入性等方法.本文描述实现可重入的一种方法:线程私有数据

堆栈和堆栈大小

正在执行的程序为执行该程序的初始(或主)线程维护一个主堆栈,并为每个从属线程维护不同的堆栈.堆栈是临时内存地址空间,用于保留子程序或函数引用调用期间的参数和自动变量.如果线程堆栈的大小太小,则可能会出现堆栈溢出,从而导致无提示数据损坏或段故障. 使用 f95 -stackvar 选项编译 Fortran 程序会强制在堆栈中分配局部变量和数组,就好像它们是自动变量.显式并行化的程序暗指对 OpenMP 程序使用 -stackvar,因为该选项可提高优化器将循环中的调用并行化的能力.(有关 -sta

线程堆栈是如何增长的

我们知道每个线程初始堆栈的默认空间是1M, 我们可以在VC编译的Linker项里进行设置,该值会被编译进最终的PE可执行文件中.线程堆栈内存包括commit部分和reserver部分,我们上面说的1M实际上指reserve部分,系统为了节约内存,并不会把所有reserve的1M都提交物理内存(commit), 所以初始只是提交部分内存. 我们可以随便找一个程序,通过WinDbg进行验证:!address -f:stack BaseAddr EndAddr+1 RgnSize Type State

探究Linux进程及线程堆栈专题&lt;一&gt;

“你定义了那么多全局变量,系统才给你分配了几百KB,这样做是不是太耗内存了?”,一同学问道. 老早就听说嵌入式系统各种资源有限啊,不能分配大空间啊要注意节约资源之类的(...貌似米神4的配置要完爆我的thinkpad了...).那是不是全局变量的使用真的会占用很大系统内存,而系统真的才分配几百KB空间给我呢? 我不信,所以我要尝试一下: 全局变量,肯定是要占用内存的,但无论是不是全局变量,只要是已定义的变量都会占用内存,这个和是否是全局的没啥关系,只是占用的区域不一样而已(详见APUE存储器安排

进程空间分配和堆栈大小

1. Linux中进程空间的分配情况如下: 从上图可以看出,进程的空间分配:与进程相关的数据结构(页表.内核栈.task) ---> 物理内存 ---> 内核代码和数据  --->  用户栈  ---> 共享库的内存映射区 ---> 运行时堆 --->未初始化数据段.bss --->  已初始化数据段.data  --->  代码段.text 2. 进程的堆栈大小: 32位的Windows,一个进程栈的默认大小是1M,在vs中的编译属性可以修改程序运行时进程

VC++中出现stack overflow错误时修改VC++的默认堆栈大小

VC++中,在栈空间上申请存储的结构体或者类对象的数组空间时,如果数组长度过大,造成申请的栈空间超过或者逼近1MB时,程序可以编译通过,但是不能够执行起来.打到调试模式时会弹出如下图所示的栈空间越界错误对话框. 如下面的类定义: class Character { public: Character() { x0 = 0; y0 = 0; x1 = 0; y1 = 0; offsetX = 0; offsetY = 0; } unsigned int x0:10; unsigned int y0

详解μC/OS-II如何检测任务堆栈实际使用情况——即如何设置ucosii任务堆栈大小

不少屌丝同学都有类似经历吧,在使用ucosii创建任务时,关于任务堆栈大小设为多大合适搞的不清不楚,郁闷之下就随便整个数,比如就1024吧,呵呵,反正也没见得出问题,那就不多想了. 我想大多数同学都是这样做的吧.这样只是因为在一般情况下,1024确实已经足够大了,堆栈溢出的可能性很小而已.那么,如果你任务实际使用率只有很小的百分之几,一旦被你知道了,你会痛心不?我想你不痛心,μC/OS-II也会痛心的,它会觉得这个coder真是浪费啊,哈哈!顺便提醒下大家,堆和栈是完全不同的两个概念,出于国内习