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. 總結

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章