1 张图看 3 种不同的 posix 线程

2023-05-16

转载自:https://mp.weixin.qq.com/s/9wleh0fUjXd5jLh1b81ncQ

1 张图看 3 种不同的 posix 线程

原创 honeysugar MultiMCU EDU 今天

本文基于《Azure RTOS ThreadX 的 Posix 接口》,从“线程栈”在哪里的角度说一说 3 种不同的 pthread 建立方法。

1 张图看 3 种不同的 posix 线程

图片

 

图1. posix 线程

 

1、图中蓝色字标示的线程,线程栈在 posix 内存池里;

2、图中绿色字标示的线程,线程栈是一个全局数组(编译时确定好地址);

3、图中紫色字标示的线程,线程栈是动态分配的且不在 posix 内存池里。

这 3 种线程栈的位置是怎么回事?下面给出代码。

Posix 接口建立线程代码

对 ThreadX 上使用 posix 接口还不熟悉的请看《Azure RTOS ThreadX 的 Posix 接口》。

 
#define     PTHREAD0_STACK_SIZE   4096#define     PTHREAD1_STACK_SIZE   8912uint64_t    pthread_1_stack[PTHREAD1_STACK_SIZE/8];#define     PTHREAD2_STACK_SIZE   2048
pthread_t               pthread_0;pthread_attr_t          ptattr0;VOID    *pthread_0_entry(VOID *);
pthread_t               pthread_1;pthread_attr_t          ptattr1;VOID    *pthread_1_entry(VOID *);
pthread_t               pthread_2;pthread_attr_t          ptattr2;VOID    *pthread_2_entry(VOID *);
VOID    *pthread_0_entry(VOID *pthread0_input){    struct timespec thread_0_sleep_time={0,0};
    while(1)     {        thread_0_sleep_time.tv_nsec =  500*1e6;        thread_0_sleep_time.tv_sec =  0;        nanosleep(&thread_0_sleep_time,0);    }}
VOID    *pthread_1_entry(VOID *pthread1_input){    struct timespec thread_1_sleep_time={0,0};
    while(1)     {        thread_1_sleep_time.tv_nsec =  500*1e6;        thread_1_sleep_time.tv_sec =  0;        nanosleep(&thread_1_sleep_time,0);    }}
VOID    *pthread_2_entry(VOID *pthread1_input){    struct timespec thread_2_sleep_time={0,0};
    while(1)     {        thread_2_sleep_time.tv_nsec =  500*1e6;        thread_2_sleep_time.tv_sec =  0;        nanosleep(&thread_2_sleep_time,0);    }}
ULONG free_memory[128*1024 / sizeof(ULONG)];void  application_task_create (void){    VOID* storage_ptr;    struct sched_param  param;
    /* Init POSIX Wrapper      * 经过这一步 storage_ptr 指针指向的地址     * 已经被推到 posix 内存池之外了     */    UINT my_old_priority = THREADX_TASK_START_PRIORITY;    tx_thread_preemption_change(&threadx_task_start, 0, &my_old_priority);    storage_ptr = (VOID*) posix_initialize(free_memory);    tx_thread_preemption_change(&threadx_task_start, my_old_priority, &my_old_priority);
    /* Create pthread attributes for pthread 0 to pthread 2 */    pthread_attr_init(&ptattr0);     pthread_attr_init(&ptattr1);     pthread_attr_init(&ptattr2); TX_INTERRUPT_SAVE_AREA
    ptattr0.stack_size = PTHREAD0_STACK_SIZE;    ptattr1.stack_size = PTHREAD1_STACK_SIZE;    ptattr2.stack_size = PTHREAD2_STACK_SIZE;
    TX_DISABLE    TX_RESTORE    /* Create a sched_param structure */    memset(&param, 0, sizeof(param));
    /* Create pthread 0.       * 这个线程栈在 posix 内存池里     */    param.sched_priority = 6;    pthread_attr_setschedparam(&ptattr0, &param);    //pthread_attr_setstackaddr(&ptattr0,  storage_ptr );    //storage_ptr = (int *) storage_ptr + PTHREAD0_STACK_SIZE;        pthread_create (&pthread_0, &ptattr0,pthread_0_entry,NULL);
    /* Create pthread 1.       * 这个线程栈在编译时确定好的数组里     */    param.sched_priority = 7;    pthread_attr_setschedparam(&ptattr1, &param);    pthread_attr_setstackaddr(&ptattr1,  &pthread_1_stack[0] );    //storage_ptr = (int *) storage_ptr + PTHREAD1_STACK_SIZE;        pthread_create (&pthread_1, &ptattr1,pthread_1_entry,NULL);
    /* Create pthread 2.       * 这个线程栈不在内存池里,     * 而是在内存池之外的,并且是动态分配的栈空间     * 也就是说这样做无法在编译时确定栈地址在哪     */    param.sched_priority = 8;    pthread_attr_setschedparam(&ptattr2, &param);    pthread_attr_setstackaddr(&ptattr2,  storage_ptr );    storage_ptr = (int *) storage_ptr + PTHREAD2_STACK_SIZE;        pthread_create (&pthread_2, &ptattr2,pthread_2_entry,NULL);}

3 种写法该怎么选

首先,要清楚一个非常重要的基本观点:安全关键的项目基本是不考虑动态内存分配的。

最优写法

Sugar 觉得不论项目是否是“安全关键”的,最好是按“安全关键”的习惯来写。从内存分配的角度来讲,如果要实现安全关键,最好是程序员知道线程栈的地址。所以 Sugar 认为最优写法是把线程栈放到代码里写的全局数组当中。

图片

 

图2. 程序员知道的线程栈

 

次优写法

如果不想通过全局数组指定线程栈(比如程序员水平仍需提高)时,则可以把线程栈放到操作系统的内存池里,操作系统都会有自己的内存管理,由其像 ThreadX 这种过了最高等级安全认证的,其内存管理是能经得住考验的。

凑合用写法

如果程序员不知道线程栈在哪里,同时线程栈也不出自于操作系统的内存池(不在内存管理泛围),也就是说完全由动态分配来确定线程栈地址,万一程序需要 Debug 则会给开发者带来不必要的麻烦。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1 张图看 3 种不同的 posix 线程 的相关文章

随机推荐