干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?

摘要 學過用過FreeRTOS的人都知道,在創(chuàng)建任務(wù)時候我們都要定義一個任務(wù)句柄,這個任務(wù)句柄有啥含義? 書上的解釋是任務(wù)創(chuàng)建成功以后會返回此任務(wù)的任務(wù)句柄,這個句柄就是 任務(wù)的堆棧 此參數(shù)就用來保存這個任務(wù)句柄。 其他API函數(shù)可能會使用到這個句柄。

那么任務(wù)句柄是到底是怎么一回事,它保存的是任務(wù)控制塊的首地址。那么它又是如何來保存任務(wù)的首地址呢?這就是我們今天要討論的話題。我盡量寫得通俗易懂,讓大家都能輕松理解

1、創(chuàng)建一個任務(wù)

動態(tài)創(chuàng)建一個任務(wù)

#define TASK1_TASK_PRIO  1    //任務(wù)優(yōu)先級
#define TASK1_STK_SIZE   128    //任務(wù)棧大小 
TaskHandle_t Task1Task_Handler;  //任務(wù)句柄
//動態(tài)創(chuàng)建一個任務(wù)1
xTaskCreate((TaskFunction_t )task1_task,            //任務(wù)函數(shù)  
            (const char*    )"task1_task",          //任務(wù)名稱  
            (uint16_t       )TASK1_STK_SIZE,        //任務(wù)堆棧大小
            (void*          )NULL,                  //傳遞給任務(wù)函數(shù)的參數(shù)   
            (UBaseType_t    )TASK1_TASK_PRIO,       //任務(wù)優(yōu)先級
            (TaskHandle_t*  )&Task1Task_Handler);   //任務(wù)句柄   

//task1任務(wù)函數(shù)
void task1_task(void *pvParameters)
{
 for(;;)
 {  
      vTaskDelay( 2000 );
 }
}
干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖1

參數(shù):

  • pxTaskCode:任務(wù)函數(shù)。
  • pcName:任務(wù)名字,一般用于追蹤和調(diào)試,任務(wù)名字長度不能超過。 configMAX_TASK_NAME_LEN ,在 FreeRTOSConfig.h 文件中宏定義為16。
  • usStackDepth:任務(wù)堆棧大小,實際申請到的堆棧是 usStackDepth 的4倍。其中空閑任務(wù)的任務(wù)堆棧大小為 configMINIMAL_STACK_SIZE ,在 FreeRTOSConfig.h 文件中宏定義為130(字)。
  • pvParameters:傳遞給任務(wù)函數(shù)的參數(shù)。
  • uxPriority:任務(wù)優(yōu)先級,范圍 0—configMAX_PRIORITIES-1 ,在 FreeRTOSConfig.h 文件中 configMAX_PRIORITIES 宏定義為32。
  • pxCreatedTask:任務(wù)句柄,任務(wù)創(chuàng)建成功以后會返回此任務(wù)的任務(wù)句柄,這個句柄其實就是任務(wù)的任務(wù)堆棧。此參數(shù)就用來保存這個任務(wù)句柄。其他API函數(shù)可能會使用到這個句柄。

返回值:

  • pdPASS:任務(wù)創(chuàng)建成功。pdPASS宏定義為1
  • errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY :任務(wù)創(chuàng)建失敗,因為堆內(nèi)存不足!

在創(chuàng)建一個任務(wù)時一般都會在程序開頭都有這三個宏定義

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖2

要指定任務(wù)的優(yōu)先級、任務(wù)的棧大小,以及任務(wù)的句柄。

優(yōu)先級很好理解,它決定了多個任務(wù)之間執(zhí)行任務(wù)的先后順序,任務(wù)的棧大小也很理解,在創(chuàng)建任務(wù)時,任務(wù)的局部變量以及任務(wù)切換時的數(shù)據(jù)都保存在棧里面。那么任務(wù)句柄是怎么一回事,它保存的是任務(wù)控制塊的首地址。那么它又是如何來保存任務(wù)的首地址呢?這就是我們今天要討論的話題

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖3

創(chuàng)建任務(wù)是時傳入的是一個指針?

是一個指針嗎?

不是,是一個指針的指針。

為什么要傳入指針的指針?

什么是指針的指針?

這些問題都需要搞明白你才能解決這個問題?

二、二級指針

正好前兩天看到了這樣一篇文章,里面有一道C語言的題可以引用來解釋我們今天的問題,我們一起來看一下

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖4

上面這個代碼有好幾處錯誤,它的目的很簡單,就是想把字符串hello world拷貝給str,但是它能拷貝成功嗎?

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖5

很顯然是不可以的。

為了使大家看的更清楚,代碼簡單修改一下

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmemory(char *p)
{
   p = (char *) malloc(100);
   strcpy(p,"www.zhiguoxin.cn");
   printf("*p:%s  &(*p):0x%x\r\n",p,&p);
}
int main()
{
  char *str="www.baidu.cn";
  getmemory(str);
  printf("str:%s  &str:0x%x\r\n",str,&str);
  free(str);
  return 0;
}

按照我們一般人的的想法,結(jié)果應(yīng)該是:

p  :www.zhiguoxin.cn &p  :xxxxxxx
str:www.zhiguoxin.cn &str:xxxxxxx

但是實際上結(jié)果是多少?

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖6

完全沒有變化,為了徹底解決這個問題,畫了一個圖,希望大家能夠看的更加清楚一點。

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖7

從這里可以看出來,在分配內(nèi)存后,strp就分道揚鑣了,而str也還是指向www.baidu.cn

如何修改呢?正確的是啥樣的?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmemory(char **p)
{
   *p = (char *) malloc(100);
   strcpy(*p,"www.zhiguoxin.cn");
   printf("*p:%s  &(*p):0x%x\r\n",*p,&(*p));
}
int main()
{
  char *str="www.baidu.cn";
  getmemory(&str);
  printf("str:%s  &str:0x%x\r\n",str,&str);
  free(str);
  return 0;
}

編譯運行,發(fā)現(xiàn)沒問題。

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖8

達到了我們想要的目的,字符串也得到了正常的拷貝。

如何解釋?

函數(shù)中參數(shù)都是傳值,傳指針本質(zhì)上也是傳值,只不過它的值是指針類型罷了。如果想要改變?nèi)雲(yún)?nèi)容,則需要傳該入?yún)⒌牡刂罚ㄟ^解引用修改其指向的內(nèi)容

這里的str的值就是*p的值,是多少?它們都是一個指針,就是保存的是一個地址,地址是多少?地址就是使用動態(tài)分配內(nèi)存malloc函數(shù)分配的100字節(jié)的首地址。然后又使用strcpy()函數(shù)將hello world拷貝到*p里面。

這里面就涉及到了二級指針,首先str毫無疑問是一個指針變量對吧?那么&str是啥?理所當然就是一個指針的指針吧,就是地址的地址。

所以,我如果在某個地方申請了一塊內(nèi)存,如果想得到這塊內(nèi)存的首地址,而此時我們又定義了一個指針變量,想讓這個指針來保存我們申請內(nèi)存你的首地址,就必須要傳入這個指針的地址,即指針的指針(二級指針)而不是傳入這個指針。

至于原因上面的例子已經(jīng)非常清楚的講解了原因。

下面接著回到我們最開始的創(chuàng)建函數(shù)的任務(wù)句柄。在開始之前我們再把上面的函數(shù)封裝一下。

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖9
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char* TaskHandle_t;

void getmemory(TaskHandle_t *p)
{
   *p = (char *) malloc(100);
   strcpy(*p,"www.zhiguoxin.cn");
   printf("*p:%s  &(*p):0x%x\r\n",*p,&(*p));
}
int main()
{
  TaskHandle_t str;
  getmemory(&str);
  printf("str:%s  &str:0x%x\r\n",str,&str);
  free(str);
  return 0;
}

沒啥大不了的,就是就是給char*起了一個別名而已,讓下面的代碼看起來更加順暢一寫。

干貨|FreeRTOS中的任務(wù)句柄到底是什么意思?的圖10

這樣對比一下是不是很清楚了呢?這樣一來我們創(chuàng)建任務(wù)時候這個任務(wù)句柄就保存的是我們TCB控制塊這個結(jié)構(gòu)體的首地址了,知道了一個任務(wù)的TCB控制塊首地址的話,那么這個任務(wù)的所有信息我是不是都知道了。是的,就是這么奇妙。通過指針的指針,二級指針來轉(zhuǎn)換一下。

登錄后免費查看全文
立即登錄
App下載
技術(shù)鄰APP
工程師必備
  • 項目客服
  • 培訓(xùn)客服
  • 平臺客服

TOP