线程本地存储指针允许开发者存储值到任务的控制块(control block)中,使这个值对于任务来说是特定且唯一的。

    线程本地存储经常被用来存储数据,而单一进程的应用程序通常的做法是使用全局变量。比如,很多库函数包含一个全局的返回值—错误信息,应用根据这个错误信息判读错误类型,同时进行相应处理。在单线程的应用中可以使用全局变量来保存这个错误信息,但是在多任务的系统中,每个任务都必须有一个自己的位置去存储这个错误信息,否则的话,会导致一个任务读取到另外一个任务的错误信息的混乱情况。

    freeRTOS提供给开发者一个很灵活的实现线程本地存储的机制—-使用线程本地存储指针。

    configNUM_THREAD_LOCAL_STORAGE_POINTERS配置任务数组大小(以void *的大小为单位)。vTaskSetThreadLocalStoragePointer()写入数据到线程的本地存储,pvTaskGetThreadLocalStoragePointer()读取线程本地存储的数据。示例如下:

    大小小于等于空类型的指针(void *)的大小的变量可以直接存在线程本地存储指针指向的数组。如果sizeof( void * )等于4个字节,那么32-bit的数可以直接存入。

    1. uint32_t ulVariable;
    2. /* 写 32-bit 的数据 0x12345678 到线程本地存储数组的索引1的
    3. 位置上,NULL,代表写入当前调用的任务的本地存储*/
    4. vTaskSetThreadLocalStoragePointer( NULL, /* 任务句柄. */
    5. 1, /* 数组索引 */
    6. ( void * ) 0x12345678 );
    7. ulVariable = ERROR_CODE;
    8. vTaskSetThreadLocalStoragePointer( NULL, /* 任务句柄 */
    9. 0, /* 数组索引*/
    10. ( void * ) ulVariable );
    11. /* 读取索引5的数据. */
    12. ulVariable = ( uint32_t ) pvTaskGetThreadLocalStoragePointer( NULL, 5 );

    上面的例子演示了如何存取一个数值,下面的例子演示了如何存取结构体的指针:

    1. typedef struct
    2. {
    3. uint32_t ulValue1;
    4. uint32_t ulValue2;
    5. } xExampleStruct;
    6. xExampleStruct *pxStruct;
    7. /* 创建这个任务使用的结构体 */
    8. pxStruct = pvPortMalloc( sizeof( xExampleStruct ) );
    9. /* 设置结构体成员 */
    10. pxStruct->ulValue1 = 0;
    11. pxStruct->ulValue2 = 1;
    12. /* 保存结构体指针到数组的索引0处 */
    13. vTaskSetThreadLocalStoragePointer( NULL, /* Task handle. */
    14. 0, /* Index into the array. */
    15. ( void * ) pxStruct );
    16. /* 读取保存在线程本地存储的指针 */
    17. pxStruct = ( xExampleStruct * ) pvTaskGetThreadLocalStoragePointer( NULL, 0 );