目录
SylixOS是多线程操作系统,系统能够同时创建多个线程,具体最大线程数量取决于系统内存的大小以及编译SylixOS操作系统时的相关配置,SylixOS线程默认最大线程数量由宏LW_CFG_MAX_THREADS决定,该宏定义可以在文件<config/kernel/kernel_cfg.h>中发现。
线程有时被称为轻量级进程(Lightweight Process,LWP),在SylixOS中线程又被称为任务,是某个单一顺序的指令流,也是操作系统调度的最小单位,并且每个线程都拥有自己的优先级。一个线程通常由线程句柄(或ID)、当前指令(PC)、CPU寄存器集合、线程栈四个部分组成。
每个线程都有自己独立的栈区,每一个线程控制块保存了栈区的起始位置、终止位置、以及栈警戒点(用于栈溢出检查)。当发生任务调度是,线程栈区将保存线程的当前环境(用于上下文恢复)。因此线程栈的设置必须合理,太大将浪费内存空间,太小可能会引起栈溢出。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 | 获得线程属性块栈填充特性 |
…… | …… |
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; |
栈大小的设置没有可以套用的公式,通常根据开发者经验设置一个较大的值,用存储空间换取可靠性。在正常进程启动情况下,会继承内核线程栈大小。如果创建线程是不设置线程栈属性,将会继承内核Shell线程的栈大小。如程序清单 22所示:
程序清单 22 堆栈大小的函数
intpthread_attr_setstacksize (pthread_attr_t *pattr, size_tstSize) |
通过shell指令ss可以查看栈的大小,如图 21所示:
图 21 shell指令查看栈大小
因为我们无法确定所需使用栈区的实际大小,我们通过设置堆栈警戒区的方式来防止堆栈溢出,系统设置默认的警戒区大小为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应用程序开发手册》
原文地址:http://12738386.blog.51cto.com/12728386/1927468