当前位置: 首页 > article >正文

在FreeRTOS中动态创建任务,假如在最后一个参数写NULL,该任务有任务句柄吗

在 FreeRTOS 中,当你使用 xTaskCreate() 或其他类似函数动态创建任务时,最后一个参数是指向 TaskHandle_t 类型变量的指针。这个参数用于接收新创建任务的任务句柄(task handle)。如果你在这个参数中传递 NULL,那么你将不会获得该任务的任务句柄。

任务句柄的作用

任务句柄是一个非常有用的工具,它允许你在之后的操作中引用特定的任务。例如:

  • 删除任务:使用 vTaskDelete() 函数可以终止并删除一个任务。
  • 挂起/恢复任务:使用 vTaskSuspend() 和 vTaskResume() 可以控制任务的执行状态。
  • 更改任务优先级:使用 vTaskPrioritySet() 可以调整任务的优先级。
  • 发送通知给任务:使用 xTaskNotifyGive() 等函数可以向任务发送通知。

当传递 NULL 作为任务句柄参数时

如果你在调用 xTaskCreate() 时传递 NULL 作为最后一个参数,那么虽然任务仍然会被成功创建并且可以正常运行,但你将无法通过任务句柄直接对该任务进行上述操作。这并不意味着任务没有句柄——FreeRTOS 内部仍然会为每个任务维护一个句柄,只是你无法从外部获取和使用它。

示例代码

BaseType_t xReturned;

// 创建任务并获取任务句柄
xReturned = xTaskCreate(
    vTaskCode,           // 任务函数
    "TaskName",          // 任务名称
    STACK_SIZE,          // 栈大小
    (void *)param,       // 传递给任务函数的参数
    tskIDLE_PRIORITY + 1,// 任务优先级
    &xHandle);           // 任务句柄指针

if (xReturned == pdPASS)
{
    // 任务创建成功,并且可以通过 xHandle 操作任务
}

// 创建任务但不获取任务句柄
xReturned = xTaskCreate(
    vTaskCode,           // 任务函数
    "TaskName",          // 任务名称
    STACK_SIZE,          // 栈大小
    (void *)param,       // 传递给任务函数的参数
    tskIDLE_PRIORITY + 1,// 任务优先级
    NULL);               // 不需要任务句柄

if (xReturned == pdPASS)
{
    // 任务创建成功,但没有保存任务句柄
}

总结

  • 传递非 NULL 的任务句柄指针:你可以稍后使用该句柄来管理和控制任务。
  • 传递 NULL:任务仍然会被创建并运行,但你将无法通过任务句柄对其进行管理。

因此,是否需要传递 NULL 取决于你是否计划在未来对任务进行额外的操作。如果你不需要这些功能,传递 NULL 是完全可以接受的做法;否则,建议保留任务句柄以便后续使用。

如果再用xTaskGetCurrentTaskHandle()能获取到句柄吗

xTaskGetCurrentTaskHandle() 函数用于获取当前正在执行的任务的句柄。如果你在任务内部调用这个函数,它将返回该任务自己的任务句柄。因此,即使你在创建任务时没有通过 xTaskCreate() 的最后一个参数保存任务句柄(即传递了 NULL),你仍然可以在任务内部使用 xTaskGetCurrentTaskHandle() 来获取其自身的句柄。

使用场景

  • 任务自我管理:如果一个任务需要对自己进行某些操作(如挂起自己、改变自己的优先级等),它可以使用 xTaskGetCurrentTaskHandle() 来获得自己的句柄。

  • 外部任务管理:对于那些需要从外部管理的任务,最好是在创建时就保存它们的句柄。然而,如果某个任务偶尔需要从外部被管理,并且你不希望总是传递和保存它的句柄,那么可以让该任务在需要的时候调用 xTaskGetCurrentTaskHandle() 并将其句柄发送给另一个任务或存储在一个全局变量中。

示例代码

假设我们有一个任务 task1,它在创建时没有保存任务句柄(即传递了 NULL)。我们可以在任务内部获取并打印其句柄:

void task1(void *pvParameters)
{
    TaskHandle_t xTaskHandle;

    // 获取当前任务的句柄
    xTaskHandle = xTaskGetCurrentTaskHandle();

    // 打印任务句柄(注意:具体的打印格式取决于你的调试环境)
    printf("Task1 handle is %p\r\n", xTaskHandle);

    while (1)
    {
        // 任务逻辑...
        vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒延迟一次
    }
}

void freertos_start(void)
{
    BaseType_t xReturned;

    /* 创建任务但不获取任务句柄 */
    xReturned = xTaskCreate(
        task1,
        "task1",
        TASK1_STACK_SIZE,
        NULL,
        TASK1_PRIORITY,
        NULL); // 不保存任务句柄

    if (xReturned != pdPASS)
    {
        // 处理任务创建失败的情况
        printf("Failed to create task1.\r\n");
        while (1);
    }

    /* 启动调度器 */
    vTaskStartScheduler();
}

在这个例子中,尽管我们在创建 task1 时没有保存它的句柄,但它仍然能够在运行时通过 xTaskGetCurrentTaskHandle() 获取到自己的句柄。

注意事项

  • 只能获取当前任务的句柄xTaskGetCurrentTaskHandle() 只能用于获取调用此函数的任务的句柄。如果你想从其他任务或中断上下文中获取不同任务的句柄,则必须在创建这些任务时保存它们的句柄。

  • 线程安全性:由于 xTaskGetCurrentTaskHandle() 是在任务上下文中调用的,因此它是线程安全的,不会引起竞争条件。

总结

  • 如果你需要从任务内部管理自身,可以使用 xTaskGetCurrentTaskHandle() 来获取当前任务的句柄。
  • 对于需要从外部管理的任务,建议在创建时保存它们的句柄以供后续使用。

http://www.kler.cn/a/449271.html

相关文章:

  • 安装管理docker
  • 重温设计模式--享元模式
  • 路由器做WPAD、VPN、透明代理中之间一个
  • CSS系列(24)-- 打印样式详解
  • 基于JAVA_JSP电子书下载系统的设计与实现【源码+文档+部署讲解】
  • 设计模式详解(十二):单例模式——Singleton
  • 如何注册和使用Facebook企业号
  • uniapp验证码
  • 数据库管理-第274期 Oracle Enterprise Manager 24ai新特性一览(20241223)
  • 使用frp进行内网穿透
  • 程控电阻箱应用中需要注意哪些安全事项?
  • Log4j简介
  • 在Excel中绘制ActiveX控件:解决文本编辑框定位问题
  • ubuntu装P104
  • 操作系统(22)外存的组织方式
  • 初识Go语言
  • docker部署微信小程序自动构建发布和更新
  • “电找车“ | 助力移动充电机器人快速落地
  • Could not resolve host: github.com
  • Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍