默認情況下,移植完FreeRTOS系統後,errno變量並不是線程安全的,所有的線程都是共用一個全局的errno變量。
爲了解決這個問題,可以重寫Keil MDK的__aeabi_errno_addr函數重新指定errno變量的存放位置,使其返回FreeRTOS定義的FreeRTOS_errno全局變量的地址。
volatile int *__aeabi_errno_addr(void)
{
extern int FreeRTOS_errno;
// 從任務A切換到任務B時, FreeRTOS會將errno值保存到A任務的TaskHandle_t結構體裏面, 然後將B任務的errno值從TaskHandle_t恢復到這個變量中
return &FreeRTOS_errno;
}
FreeRTOS的FreeRTOS_errno功能必須啓用configUSE_POSIX_ERRNO選項後才能使用。於是在FreeRTOSConfig.h中添加:
#define configUSE_POSIX_ERRNO 1
測試代碼:
sqrt(-10);
printf("%s: errno=%d\n", __FUNCTION__, errno);
在一個線程中執行sqrt(-10)後,errno變爲非零值。此時另一個線程中打印errno變量的值,結果仍爲0。
這樣就能徹底解決errno線程不安全的問題。