摘要:学过用过FreeRTOS的人都知道,在创建任务时候我们都要定义一个任务句柄,这个任务句柄有啥含义?书上的解释是任务创建成功以后会返回此任务的任务句柄,这个句柄就是任务的堆栈。此参数就用来保存这个任务句柄。其他API函数可能会使用到这个句柄。
那么任务句柄是到底是怎么一回事,它保存的是任务控制块的首地址。那么它又是如何来保存任务的首地址呢?这就是我们今天要讨论的话题。我尽量写得通俗易懂,让大家都能轻松理解。
1、创建一个任务
动态创建一个任务
#defineTASK1_TASK_PRIO1//任务优先级
#defineTASK1_STK_SIZE128//任务栈大小
TaskHandle_tTask1Task_Handler;//任务句柄
//动态创建一个任务1
xTaskCreate((TaskFunction_t)task1_task,//任务函数
(constchar*)"task1_task",//任务名称
(uint16_t)TASK1_STK_SIZE,//任务堆栈大小
(void*)NULL,//传递给任务函数的参数
(UBaseType_t)TASK1_TASK_PRIO,//任务优先级
(TaskHandle_t*)&Task1Task_Handler);//任务句柄
//task1任务函数
voidtask1_task(void*pvParameters)
{
for(;;)
{
vTaskDelay(2000);
}
}
参数:
- pxTaskCode:任务函数。
-
pcName:任务名字,一般用于追踪和调试,任务名字长度不能超过。
configMAX_TASK_NAME_LEN
,在FreeRTOSConfig.h
文件中宏定义为16。 -
usStackDepth:任务堆栈大小,实际申请到的堆栈是
usStackDepth
的4倍。其中空闲任务的任务堆栈大小为configMINIMAL_STACK_SIZE
,在FreeRTOSConfig.h
文件中宏定义为130(字)。 - pvParameters:传递给任务函数的参数。
-
uxPriority:任务优先级,范围
0—configMAX_PRIORITIES-1
,在FreeRTOSConfig.h
文件中configMAX_PRIORITIES
宏定义为32。 - pxCreatedTask:任务句柄,任务创建成功以后会返回此任务的任务句柄,这个句柄其实就是任务的任务堆栈。此参数就用来保存这个任务句柄。其他API函数可能会使用到这个句柄。
返回值:
- pdPASS:任务创建成功。pdPASS宏定义为1
-
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
:任务创建失败,因为堆内存不足!
在创建一个任务时一般都会在程序开头都有这三个宏定义
要指定任务的优先级、任务的栈大小,以及任务的句柄。
优先级很好理解,它决定了多个任务之间执行任务的先后顺序,任务的栈大小也很理解,在创建任务时,任务的局部变量以及任务切换时的数据都保存在栈里面。那么任务句柄是怎么一回事,它保存的是任务控制块的首地址。那么它又是如何来保存任务的首地址呢?这就是我们今天要讨论的话题。
创建任务是时传入的是一个指针?
是一个指针吗?
不是,是一个指针的指针。
为什么要传入指针的指针?
什么是指针的指针?
这些问题都需要搞明白你才能解决这个问题?
二、二级指针
正好前两天在公众号看到了这样一篇文章,里面有一道C语言的题可以引用来解释我们今天的问题,我们一起来看一下
上面这个代码有好几处错误,它的目的很简单,就是想把字符串hello world
拷贝给str
,但是它能拷贝成功吗?
很显然是不可以的。
为了使大家看的更清楚,代码简单修改一下
#include
#include
#include
voidgetmemory(char*p)
{
p=(char*)malloc(100);
strcpy(p,"www.zhiguoxin.cn");
printf("*p:%s&(*p):0x%x
",p,&p);
}
intmain()
{
char*str="www.baidu.cn";
getmemory(str);
printf("str:%s&str:0x%x
",str,&str);
free(str);
return0;
}
按照我们一般人的的想法,结果应该是:
p:www.zhiguoxin.cn&p:xxxxxxx
str:www.zhiguoxin.cn&str:xxxxxxx
但是实际上结果是多少?
完全没有变化,为了彻底解决这个问题,画了一个图,希望大家能够看的更加清楚一点。
从这里可以看出来,在分配内存后,str
与p
就分道扬镳了,而str也还是指向www.baidu.cn
。
如何修改呢?正确的是啥样的?
#include
#include
#include
voidgetmemory(char**p)
{
*p=(char*)malloc(100);
strcpy(*p,"www.zhiguoxin.cn");
printf("*p:%s&(*p):0x%x
",*p,&(*p));
}
intmain()
{
char*str="www.baidu.cn";
getmemory(&str);
printf("str:%s&str:0x%x
",str,&str);
free(str);
return0;
}
编译运行,发现没问题。
达到了我们想要的目的,字符串也得到了正常的拷贝。
如何解释?
函数中参数都是传值,传指针本质上也是传值,只不过它的值是指针类型罢了。如果想要改变入参内容,则需要传该入参的地址,通过解引用修改其指向的内容。
这里的str
的值就是*p
的值,是多少?它们都是一个指针,就是保存的是一个地址,地址是多少?地址就是使用动态分配内存malloc函数分配的100字节的首地址。然后又使用strcpy()
函数将hello world
拷贝到*p
里面。
这里面就涉及到了二级指针,首先str
毫无疑问是一个指针变量对吧?那么&str
是啥?理所当然就是一个指针的指针吧,就是地址的地址。
所以,我如果在某个地方申请了一块内存,如果想得到这块内存的首地址,而此时我们又定义了一个指针变量,想让这个指针来保存我们申请内存你的首地址,就必须要传入这个指针的地址,即指针的指针(二级指针)而不是传入这个指针。
至于原因上面的例子已经非常清楚的讲解了原因。
下面接着回到我们最开始的创建函数的任务句柄。在开始之前我们再把上面的函数封装一下。
#include
#include
#include
typedefchar*TaskHandle_t;
voidgetmemory(TaskHandle_t*p)
{
*p=(char*)malloc(100);
strcpy(*p,"www.zhiguoxin.cn");
printf("*p:%s&(*p):0x%x
",*p,&(*p));
}
intmain()
{
TaskHandle_tstr;
getmemory(&str);
printf("str:%s&str:0x%x
",str,&str);
free(str);
return0;
}
没啥大不了的,就是就是给char*
起了一个别名而已,让下面的代码看起来更加顺畅一写。
这样对比一下是不是很清楚了呢?这样一来我们创建任务时候这个任务句柄就保存的是我们TCB控制块这个结构体的首地址了,知道了一个任务的TCB控制块首地址的话,那么这个任务的所有信息我是不是都知道了。是的,就是这么奇妙。通过指针的指针,二级指针来转换一下。
原文标题:干货 | FreeRTOS中的任务句柄到底是什么意思?
文章出处:【微信公众号:电子工程世界】欢迎添加关注!文章转载请注明出处。
-
函数
+关注
关注
3文章
4303浏览量
62411 -
FreeRTOS
+关注
关注
12文章
483浏览量
61992 -
任务
+关注
关注
1文章
20浏览量
8531
原文标题:干货 | FreeRTOS中的任务句柄到底是什么意思?
文章出处:【微信号:电子工程世界,微信公众号:电子工程世界】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论