【问题标题】:Why can I pass an integer as a task parameter but can't pass a struct variable?为什么我可以将整数作为任务参数传递,但不能传递结构变量?
【发布时间】:2020-01-05 11:57:56
【问题描述】:

我试图将一组参数传递给一个任务。所以我创建了一个结构并将其传递给我的任务,如下所示:

my_type_t parameters_set;

//... assigning values to parameters_set

xTaskCreate( vMyTask, "MyTask", STACK_SIZE, (void*)parameters_set, 2,
 &xHandle);

在我的任务中,我尝试通过以下操作检索结构值:

my_type_t received_parameters = (my_type_t) pvParameters;

任务创建行在编译时触发以下错误:“无法转换为指针类型”,结构检索行触发“请求转换为非标量类型”错误。我知道如果我使用指针而不是变量本身,它会编译,但我不能这样做,因为创建任务的函数将会死掉,并且任务将引用一个不再存在的变量。最后我将使用一个全局结构变量。

但我真正想了解的是为什么任务接受 int 值(不是通过引用),而不接受 typedef 结构?例如,下面的 sn-p 可以毫无问题地构建和工作:

//Inside the function that creates the task
int x = 0;

xTaskCreate( vMyTask, "MyTask", STACK_SIZE, (void*)x, 2,
 &xHandle);

//Inside the Task
int received_parameter = (int) pvParameters;

提前致谢!

【问题讨论】:

  • 结构不能转换为指针。只有指向struct的指针才可以。将 int 转换为 void* 也不正确。请发帖minimal reproducible example

标签: c operating-system task freertos


【解决方案1】:

您显示的代码没有将int 值作为参数。您使用(void*)x 传递参数,这是一个将int x 转换为指针的表达式。

函数xTaskCreate 接受一个指针。你给了它一个指针,所以编译器不会抱怨。但是,您给它的指针不是 指向 x 的指针(将被写为&x),而是一个指针 @的值转换而来987654329@。尽管编译器没有抱怨,但这通常不是正确的传递给xTaskCreate

这不适用于结构的原因是当parameters_set 是结构时,(void*)parameters_set 不是正确的表达式。这是因为 C 允许将整数转换为指针,但不提供将结构转换为指针。一般来说,整数和指针之间有一种自然的对应关系:在“平坦”的地址空间中,内存中的每个字节都有一个地址,而这些地址本质上是从内存地址空间的“开始”开始的字节数。所以一个整数可以作为一个地址,反之亦然。 (在其他地址空间中,对应关系可能更复杂,但 C 仍然允许转换,但有一些规则。)因此,当您编写 (void*)x 时,编译器会将 x 中的整数值转换为指针。

结构体和指针之间没有这种对应关系,所以C标准没有定义任何结构体到指针的转换,你写(void*)parameters_set时编译器报错。

你应该为这个参数传递的是地址一些数据给任务。如果您希望任务具有x 中的数据,则应通过&x。如果您希望任务具有parameters_set 中的数据,则应通过&parameters_set& 运算符获取其操作数的地址,这与使用 (void*) 强制转换不同,后者试图将其操作数转换为指针。

根据RTOS documentation for xTaskCreate,您不应传递“堆栈变量”的地址,对于C,它实际上意味着具有自动存储持续时间的对象。换句话说,您不应该传递在没有static 的函数中定义的xparameters_set 或(可能取决于RTOS 和C 实现的安排;我不熟悉RTOS)_Thread_local .或者,您可以使用 malloc(或者,根据下面的评论,pvPortMalloc 用于 RTOS)为参数分配空间并将其传递给 xTaskCreate

【讨论】:

  • 如果您使用的是 FreeRTOS,您应该使用 pvPortMalloc(),以便 RTOS 可以处理内存管理。
  • @theSealion:谢谢,注意到了。 RTOS 中pvPortMallocmalloc 有什么区别?
  • 'pvPortMalloc' 是来自 FreeRTOS 的 malloc 实现。如果您使用的是 RTOS,这将与其余的内存管理一起工作得更好。
猜你喜欢
  • 2016-08-16
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
相关资源
最近更新 更多