【2】STM32·FreeRTOS·任务创建和删除

目录

一、任务创建和删除的API函数

1.1、动态创建任务函数

1.2、静态创建任务函数

1.3、任务删除函数

二、任务创建和删除(动态方法)

三、任务创建和删除(静态方法)


一、任务创建和删除的API函数

任务的创建和删除本质就是调用 FreeRTOS 的 API 函数

API函数描述

xTaskCreate()

动态方式创建任务
xTaskCreateStatic()静态方式创建任务
xTaskDelete()删除任务

动态创建任务:任务的任务控制块以及任务的栈空间所需的内存,均由 FreeRTOS 从 FreeRTOS 管理的堆中分配

静态创建任务:任务的任务控制块以及任务的栈空间所需的内存,需用户分配提供

1.1、动态创建任务函数

BaseType_t xTaskCreate
(
    TaskFunction_t                  pxTaskCode,      /* 指向任务函数的指针 */
    const char * const              pcName,          /* 任务名字,最大长度configMAX_TASK_NAME_LEN */
    const configSTACK_DEPTH_TYPE    usStackDepth,    /* 任务堆栈大小,注意字为单位 */
    void * const                    pvParameters,    /* 传递给任务函数的参数 */
    UBaseType_t                     uxPriority,      /* 任务优先级,范围:0 ~ configMAX_PRIORITIES - 1 */
    TaskHandle_t * const            pxCreatedTask    /* 任务句柄,就是任务的任务控制块 */
)
返回值描述
pdPASS任务创建成功

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY

任务创建失败

实现动态创建任务流程

1、将宏 configSUPPORT_DYNAMIC_ALLOCATION 配置为 1

2、定义函数入口参数

3、编写任务函数

此函数创建的任务会立刻进入就绪态,由任务调度器调度运行

动态创建任务函数内部实现

1、申请堆栈内存&任务控制块内存

2、TCB结构体成员赋值

3、添加新任务到就绪列表中

任务控制块结构体成员介绍

typedef struct tskTaskControlBlock
{
    volatile StackType_t      *pxTopOfStack;                           /* 任务栈栈顶,必须为TCB的第一个成员 */
    ListItem_t                xStateListItem;                          /* 任务状态列表项 */
    ListItem_t                xEventListItem;                          /* 任务事件列表项 */
    UBaseType_t               uxPriority;                              /* 任务优先级,数值越大,优先级越大 */
    StackType_t               *pxStack;                                /* 任务栈起始地址 */
    char                      pcTaskName[configMAX_TASK_NAME_LEN];     /* 任务名字 */
    ...
} tskTCB;

任务栈栈顶,在任务切换时的任务上下文保存、任务恢复息息相关

每个任务都有属于自己的任务控制块,类似身份证

1.2、静态创建任务函数

TaskHandle_t xTaskCreateStatic
(
    TaskFunction_t          pxTaskCode,        /* 指向任务函数的指针 */
    const char * const      pcName,            /* 任务函数名 */
    const uint32_t          ulStackDepth,      /* 任务堆栈大小,注意字为单位 */
    void * const            pvParameters,      /* 传递给任务函数的参数 */
    UBaseType_t             uxPriority,        /* 任务优先级 */
    StackType_t * const     puxStackBuffer,    /* 任务堆栈,一般为数组,由用户分配 */
    StaticTask_t * const    pxTaskBuffer       /* 任务控制块指针,由用户分配 */
)
返回值描述
NULL用户没有提供相应的内存,任务创建失败

其他值

任务句柄,任务创建成功

静态创建任务使用流程

1、将宏 configSUPPORT_STATIC_ALLOCATION 配置为 1

2、定义空闲任务&定时器任务的任务堆栈及TCB

3、实现两个接口函数:vApplicationGetIdleTaskMemory()、vApplicationGetTimerTaskMemory()

4、定义函数入口参数

5、编写任务函数

此函数创建的任务会立刻进入就绪态,由任务调度器调度运行

静态创建任务函数内部实现

1、TCB结构体成员赋值

2、添加新任务到就绪列表中

1.3、任务删除函数

void vTaskDelete(TaskHandle_t xTaskToDelete);
形参描述
xTaskToDelete待删除任务的任务句柄

用于删除已被创建的任务,被删除的任务将从就绪态任务列表阻塞态任务列表挂起态任务列表事件列表中移除

1、当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)

2、当要删除任务自身时,空闲任务会负责释放被删除任务中由系统分配的内存(动态创建任务),但是由用户在任务删除前申请的内存(静态创建任务),则需要由用户在任务被删除前提前释放,否则将导致内存泄漏

删除任务流程

1、使用删除任务函数,需将宏 INCLUDE_vTaskDelete 配置为 1

2、入口参数输入需要删除的任务句柄(NULL代表删除本身)

删除任务函数内部实现

1、获取所要删除任务的控制块:通过传入的任务句柄,判断所需要删除哪个任务,NULL代表删除自身

2、将被删除任务,移除所在列表:将该任务在所在列表中移除,包括:就绪、阻塞、挂起、事件等列表

3、判断所需要删除的任务:删除任务自身,需先添加到等待删除列表,内存释放将在空闲任务执行。删除其他任务,释放内存,任务数量

4、更新下个任务的阻塞时间:更新下一个任务的阻塞超时时间,以防被删除的任务就是下一个阻塞超时的任务

二、任务创建和删除(动态方法)

将设计四个任务:start_task、task1、task2、task3

四个任务的功能如下

start_task:用来创建其他三个任务

task1:实现 LED0 每 500ms 闪烁一次

task2:实现 LED0 每 500ms 闪烁一次

task3:判断按键 KEY0 是否按下,按下则删掉 task1

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "freertos_demo.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
    delay_init(168);                    /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    led_init();                         /* 初始化LED */
    lcd_init();                         /* 初始化LCD */
    key_init();                         /* 初始化按键 */

    freertos_demo();
}

freertos_demo.c

#include "freertos_demo.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1            /* 任务优先级 */
#define START_STK_SIZE 128           /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler;      /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 */

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO 2            /* 任务优先级 */
#define TASK1_STK_SIZE 128      /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO 3            /* 任务优先级 */
#define TASK2_STK_SIZE 128      /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO 4            /* 任务优先级 */
#define TASK3_STK_SIZE 128      /* 任务堆栈大小 */
TaskHandle_t Task3Task_Handler; /* 任务句柄 */
void task3(void *pvParameters); /* 任务函数 */

/******************************************************************************************************/

/* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,
                             MAGENTA, GREEN, CYAN, YELLOW,
                             BROWN, BRRED, GRAY};

/* FreeRTOS例程入口函数 */
void freertos_demo(void)
{
    lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
    lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);
    lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);

    lcd_draw_rectangle(5, 110, 115, 314, BLACK);
    lcd_draw_rectangle(125, 110, 234, 314, BLACK);
    lcd_draw_line(5, 130, 115, 130, BLACK);
    lcd_draw_line(125, 130, 234, 130, BLACK);
    lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);
    lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);

    xTaskCreate((TaskFunction_t)start_task,          /* 任务函数 */
                (const char *)"start_task",          /* 任务名称 */
                (uint16_t)START_STK_SIZE,            /* 任务堆栈大小 */
                (void *)NULL,                        /* 传入给任务函数的参数 */
                (UBaseType_t)START_TASK_PRIO,        /* 任务优先级 */
                (TaskHandle_t *)&StartTask_Handler); /* 任务句柄 */
    vTaskStartScheduler();
}

/* start_task */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL(); /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t)task1,               /* 任务函数 */
                (const char *)"task1",               /* 任务名称 */
                (uint16_t)TASK1_STK_SIZE,            /* 任务堆栈大小 */
                (void *)NULL,                        /* 传入给任务函数的参数 */
                (UBaseType_t)TASK1_PRIO,             /* 任务优先级 */
                (TaskHandle_t *)&Task1Task_Handler); /* 任务句柄 */
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t)task2,               /* 任务函数 */
                (const char *)"task2",               /* 任务名称 */
                (uint16_t)TASK2_STK_SIZE,            /* 任务堆栈大小 */
                (void *)NULL,                        /* 传入给任务函数的参数 */
                (UBaseType_t)TASK2_PRIO,             /* 任务优先级 */
                (TaskHandle_t *)&Task2Task_Handler); /* 任务句柄 */
    /* 创建任务3 */
    xTaskCreate((TaskFunction_t)task3,               /* 任务函数 */
                (const char *)"task3",               /* 任务名称 */
                (uint16_t)TASK3_STK_SIZE,            /* 任务堆栈大小 */
                (void *)NULL,                        /* 传入给任务函数的参数 */
                (UBaseType_t)TASK3_PRIO,             /* 任务优先级 */
                (TaskHandle_t *)&Task3Task_Handler); /* 任务句柄 */
    vTaskDelete(StartTask_Handler);                  /* 删除开始任务 */
    taskEXIT_CRITICAL();                             /* 退出临界区 */
}

/* task1 */
void task1(void *pvParameters)
{
    uint32_t task1_num = 0;

    while (1)
    {
        lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);
        lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);
        LED0_TOGGLE();
        vTaskDelay(500);
    }
}

/* task2 */
void task2(void *pvParameters)
{
    uint32_t task2_num = 0;

    while (1)
    {
        lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);
        lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);
        LED1_TOGGLE();
        vTaskDelay(500);
    }
}

/* task3 */
void task3(void *pvParameters)
{
    uint8_t key = 0;

    while (1)
    {
        key = key_scan(0);

        switch (key)
        {
        case KEY0_PRES: /* 删除任务1 */
        {
            if (Task1Task_Handler != NULL)
            {
                vTaskDelete(Task1Task_Handler);
                Task1Task_Handler = NULL;
            }
            break;
        }
        case KEY1_PRES: /* 删除任务2 */
        {
            if (Task2Task_Handler != NULL)
            {
                vTaskDelete(Task2Task_Handler);
                Task2Task_Handler = NULL;
            }
            break;
        }
        default:
        {
            break;
        }
        }
        vTaskDelay(10);
    }
}

freertos_demo.h

#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H

#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/LCD/lcd.h"
#include "FreeRTOS.h"
#include "task.h"

void freertos_demo(void);

#endif

三、任务创建和删除(静态方法)

将设计四个任务:start_task、task1、task2、task3

四个任务的功能如下

start_task:用来创建其他三个任务

task1:实现 LED0 每 500ms 闪烁一次

task2:实现 LED0 每 500ms 闪烁一次

task3:判断按键 KEY0 是否按下,按下则删掉 task1

main.c、freertos_demo.h 和动态创建一样

freertos_demo.c

#include "freertos_demo.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];      /* 空闲任务任务堆栈 */
static StaticTask_t IdleTaskTCB;                                 /* 空闲任务控制块 */
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH]; /* 定时器服务任务堆栈 */
static StaticTask_t TimerTaskTCB;                                /* 定时器服务任务控制块 */

/**
 * @brief       获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的
                静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该
                有用户来提供,FreeRTOS提供了接口函数vApplicationGetIdleTaskMemory()
                实现此函数即可。
 * @param       ppxIdleTaskTCBBuffer:任务控制块内存
                ppxIdleTaskStackBuffer:任务堆栈内存
                pulIdleTaskStackSize:任务堆栈大小
 * @retval      无
 */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
                                   StackType_t **ppxIdleTaskStackBuffer,
                                   uint32_t *pulIdleTaskStackSize)
{
    *ppxIdleTaskTCBBuffer = &IdleTaskTCB;
    *ppxIdleTaskStackBuffer = IdleTaskStack;
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

/**
 * @brief       获取定时器服务任务的任务堆栈和任务控制块内存
 * @param       ppxTimerTaskTCBBuffer:任务控制块内存
                ppxTimerTaskStackBuffer:任务堆栈内存
                pulTimerTaskStackSize:任务堆栈大小
 * @retval      无
 */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
                                    StackType_t **ppxTimerTaskStackBuffer,
                                    uint32_t *pulTimerTaskStackSize)
{
    *ppxTimerTaskTCBBuffer = &TimerTaskTCB;
    *ppxTimerTaskStackBuffer = TimerTaskStack;
    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE 128                  /* 任务堆栈大小 */
StackType_t StartTaskStack[START_STK_SIZE]; /* 任务堆栈 */
StaticTask_t StartTaskTCB;                  /* 任务控制块 */
TaskHandle_t StartTask_Handler;             /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO 2                        /* 任务优先级 */
#define TASK1_STK_SIZE 128                  /* 任务堆栈大小 */
StackType_t Task1TaskStack[TASK1_STK_SIZE]; /* 任务堆栈 */
StaticTask_t Task1TaskTCB;                  /* 任务控制块 */
TaskHandle_t Task1Task_Handler;             /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO 3                        /* 任务优先级 */
#define TASK2_STK_SIZE 128                  /* 任务堆栈大小 */
StackType_t Task2TaskStack[TASK2_STK_SIZE]; /* 任务堆栈 */
StaticTask_t Task2TaskTCB;                  /* 任务控制块 */
TaskHandle_t Task2Task_Handler;             /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

/* TASK3 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK3_PRIO 4                        /* 任务优先级 */
#define TASK3_STK_SIZE 128                  /* 任务堆栈大小 */
StackType_t Task3TaskStack[TASK3_STK_SIZE]; /* 任务堆栈 */
StaticTask_t Task3TaskTCB;                  /* 任务控制块 */
TaskHandle_t Task3Task_Handler;             /* 任务句柄 */
void task3(void *pvParameters);             /* 任务函数 */

/******************************************************************************************************/

/* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,
                             MAGENTA, GREEN, CYAN, YELLOW,
                             BROWN, BRRED, GRAY};

/* FreeRTOS例程入口函数 */
void freertos_demo(void)
{
    lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
    lcd_show_string(10, 47, 220, 24, 24, "Task Create & Del", RED);
    lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);

    lcd_draw_rectangle(5, 110, 115, 314, BLACK);
    lcd_draw_rectangle(125, 110, 234, 314, BLACK);
    lcd_draw_line(5, 130, 115, 130, BLACK);
    lcd_draw_line(125, 130, 234, 130, BLACK);
    lcd_show_string(15, 111, 110, 16, 16, "Task1: 000", BLUE);
    lcd_show_string(135, 111, 110, 16, 16, "Task2: 000", BLUE);

    StartTask_Handler = xTaskCreateStatic((TaskFunction_t)start_task,     /* 任务函数 */
                                          (const char *)"start_task",     /* 任务名称 */
                                          (uint32_t)START_STK_SIZE,       /* 任务堆栈大小 */
                                          (void *)NULL,                   /* 传递给任务函数的参数 */
                                          (UBaseType_t)START_TASK_PRIO,   /* 任务优先级 */
                                          (StackType_t *)StartTaskStack,  /* 任务堆栈 */
                                          (StaticTask_t *)&StartTaskTCB); /* 任务控制块 */
    vTaskStartScheduler();
}

/* start_task */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL(); /* 进入临界区 */
    /* 创建任务1 */
    Task1Task_Handler = xTaskCreateStatic((TaskFunction_t)task1,          /* 任务函数 */
                                          (const char *)"task1",          /* 任务名称 */
                                          (uint32_t)TASK1_STK_SIZE,       /* 任务堆栈大小 */
                                          (void *)NULL,                   /* 传递给任务函数的参数 */
                                          (UBaseType_t)TASK1_PRIO,        /* 任务优先级 */
                                          (StackType_t *)Task1TaskStack,  /* 任务堆栈 */
                                          (StaticTask_t *)&Task1TaskTCB); /* 任务控制块 */
    /* 创建任务2 */
    Task2Task_Handler = xTaskCreateStatic((TaskFunction_t)task2,          /* 任务函数 */
                                          (const char *)"task2",          /* 任务名称 */
                                          (uint32_t)TASK2_STK_SIZE,       /* 任务堆栈大小 */
                                          (void *)NULL,                   /* 传递给任务函数的参数 */
                                          (UBaseType_t)TASK2_PRIO,        /* 任务优先级 */
                                          (StackType_t *)Task2TaskStack,  /* 任务堆栈 */
                                          (StaticTask_t *)&Task2TaskTCB); /* 任务控制块 */
    /* 创建任务3 */
    Task3Task_Handler = xTaskCreateStatic((TaskFunction_t)task3,          /* 任务函数 */
                                          (const char *)"task3",          /* 任务名称 */
                                          (uint32_t)TASK3_STK_SIZE,       /* 任务堆栈大小 */
                                          (void *)NULL,                   /* 传递给任务函数的参数 */
                                          (UBaseType_t)TASK3_PRIO,        /* 任务优先级 */
                                          (StackType_t *)Task3TaskStack,  /* 任务堆栈 */
                                          (StaticTask_t *)&Task3TaskTCB); /* 任务控制块 */
    vTaskDelete(StartTask_Handler);                                       /* 删除开始任务 */
    taskEXIT_CRITICAL();                                                  /* 退出临界区 */
}

/* task1 */
void task1(void *pvParameters)
{
    uint32_t task1_num = 0;

    while (1)
    {
        lcd_fill(6, 131, 114, 313, lcd_discolor[++task1_num % 11]);
        lcd_show_xnum(71, 111, task1_num, 3, 16, 0x80, BLUE);
        LED0_TOGGLE();
        vTaskDelay(500);
    }
}

/* task2 */
void task2(void *pvParameters)
{
    uint32_t task2_num = 0;

    while (1)
    {
        lcd_fill(126, 131, 233, 313, lcd_discolor[11 - (++task2_num % 11)]);
        lcd_show_xnum(191, 111, task2_num, 3, 16, 0x80, BLUE);
        LED1_TOGGLE();
        vTaskDelay(500);
    }
}

/* task3 */
void task3(void *pvParameters)
{
    uint8_t key = 0;

    while (1)
    {
        key = key_scan(0);

        switch (key)
        {
        case KEY0_PRES: /* 删除任务1 */
        {
            if (Task1Task_Handler != NULL)
            {
                vTaskDelete(Task1Task_Handler);
                Task1Task_Handler = NULL;
            }
            break;
        }
        case KEY1_PRES: /* 删除任务2 */
        {
            if (Task2Task_Handler != NULL)
            {
                vTaskDelete(Task2Task_Handler);
                Task2Task_Handler = NULL;
            }
            break;
        }
        default:
        {
            break;
        }
        }
        vTaskDelay(10);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/604987.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文件IO-使用dup2实现错误日志功能及判断文件权限,并终端输出

1:使用 dup2 实现错误日志功能 使用 write 和 read 实现文件的拷贝功能,注意,代码中所有函数后面,紧跟perror输出错误信息,要求这些错误信息重定向到错误日志 err.txt 中去 代码: #incl…

后教培时代的新东方,正在找寻更大的教育驱动力?

近段时间,K12教育主要上市公司的阶段性业绩皆已出炉。从具体数据来看,随着时间推移,教培机构的转型之路已愈走愈顺。 财报显示,2023年12月1日-2024年2月29日,好未来实现营收4.3亿美元,同比增长59.7%&#…

GIS 中的空间模式

空间模式显示了地球上事物的相互联系方式。这些图案可以是天然的或人造的。当我们使用 GIS 时,我们可以看到事物的位置以及它们之间的关系。今天,让我们关注地理和 GIS 领域的空间模式。 点分布的类型 点分布是将特定位置映射为地图上的单个点的方式。这…

W801学习笔记二十四:NES模拟器游戏

之前已经实现了NES模拟器玩游戏。W801学习笔记九:HLK-W801制作学习机/NES游戏机(模拟器) 现在要在新版本掌机中移植过来。 1、把NES文件都拷贝到SD卡中。 这回不会受内存大小限制了。我这里拷贝了4个,还可以拷贝更多。 2、应用初始化中,加载…

【运维网络篇】史上最全的 网络知识 思维导图!

01 TCP/IP网络协议栈 02 TCP/IP协议层次划分 03 传输介质简介 04 以太网帧结构 05 IP编址 06 ICMP协议 07 ARP协议 08 传输层协议 09 路由基础 10 静态路由基础 11 距离矢量路由协议——RIP 12 链路状态路由协议——OSPF 13 HDLC&PPP原理与应用 14 帧中继…

创新指南|创新组合管理的7个陷阱以及如何避免它们

进入未知领域的第一步可能具有挑战性。尽管创新会犯错误,但在将 IPM 作为公司实践实施时,您可以准备好并避免一些常见的陷阱。在这篇文章中,我们将讨论组织在实施创新组合管理时遇到的最常见的陷阱。 01. 在映射中包含日常业务任务 映射中的…

【iOS】-- 内存五大分区

【iOS】-- 内存五大分区 内存五大分区1.栈区优点: 2.堆区优点: 3.全局区4.常量区5.代码区 验证static、extern、const关键字比较1.static关键字static关键字的作用:全局静态变量局部静态变量 2.extern关键字对内的全局变量对外的全局变量 3.c…

Intel® Platform Firmware Resilience (Intel® PFR):英特尔® 平台固件恢复力(Intel® PFR)

为了降低与固件相关的安全风险,英特尔为服务器平台开发了英特尔平台固件恢复力(Intel PFR)。 此功能可保护关键固件在启动和运行时免受攻击。这可以被视为是 Cerberus 项目或 NIST SP800-193 的实现。 英特尔平台固件恢复力(Int…

抖音小店是什么?它和直播带货有什么区别和联系?一篇详解!

大家好,我是电商糖果 在网上大家都说抖音的流量大,在抖音做电商比较赚钱。 可是有很多人对抖音电商并不了解。 甚至搞不懂抖音小店是什么?它和直播带货的区别和联系也不清楚。 下面,糖果就来给大家好好解答一下这个问题。 抖音…

Linux(openEuler、CentOS8)企业内网samba服务器搭建(Windows与Linux文件共享方案)

本实验环境为openEuler系统<以server方式安装>&#xff08;CentOS8基本一致&#xff0c;可参考本文) 目录 知识点实验1. 安装samba2. 启动smb服务并设置开机启动3. 查看服务器监听状态4. 配置共享访问用户5. 创建共享文件夹6. 修改配置文件7. 配置防火墙8. 使用windows…

C++中的右值引用和移动语义

目录 1 左值引用和右值引用 2 左值引用与右值引用比较 3 右值引用使用场景和意义 4 右值引用引用左值及其一些更深入的使用场景分析 5 完美转发 6.常数右边引用 1 左值引用和右值引用 传统的C语法中就有引用的语法&#xff0c;而C11中新增了的右值引用语法特性&#xff0c…

数组中两个字符串的最小距离

给定一个字符串数组strs&#xff0c;再给定两个字符串str1和str2&#xff0c;返回在strs中str1和str2的最小距离&#xff0c;如果str1或str2为null&#xff0c;或不在strs中&#xff0c;返回-1。 输入描述&#xff1a; 输入包含有多行&#xff0c;第一输入一个整数n(1 ≤ n ≤…

Python | Leetcode Python题解之第61题旋转链表

题目&#xff1a; 题解&#xff1a; class Solution:def rotateRight(self, head: ListNode, k: int) -> ListNode:if k 0 or not head or not head.next:return headn 1cur headwhile cur.next:cur cur.nextn 1if (add : n - k % n) n:return headcur.next headwhi…

【Redis7】了解Redis

1.常见数据库 1.1.键值存储数据库 如 Map 一样的key-value 对&#xff0c;典型代表就是 Redis。 1.2.列存储数据库 关系型数据库是典型的行存储数据库&#xff0c;按行存储的数据在物理层面占用的是连续存储空间&#xff0c;不适合海量数据存储。而按列存储则可实现分布式存储&…

第七届机电、机器人与自动化国际会议(ICMRA 2024)即将召开!

第七届机电、机器人与自动化国际会议&#xff08;ICMRA 2024&#xff09;将于2024年9月20日-22日在中国武汉举行。ICMRA 2024为各国专家学者提供一个学术交流的平台&#xff0c;讨论机电、机器人和自动化领域的最新研究成果和未来的研究方向&#xff0c;旨在能够建立起国家间&a…

C语言常见的动态内存错误及几个经典笔试题以及c/c++内存开辟空间等的介绍

文章目录 前言一、常见的动态内存错误1. 对NULL指针的解引用操作2. 对动态开辟空间的越界访问3. 对非动态开辟内存使用free()4. 使用free释放一块动态开辟内存的一部分5. 对同一块动态内存多次释放6. 动态开辟内存忘记释放&#xff08;内存泄漏&#xff09; 二、几个经典笔试题…

三层交换机与防火墙连通上网实验

防火墙是一种网络安全设备&#xff0c;用于监控和控制网络流量。它可以帮助防止未经授权的访问&#xff0c;保护网络免受攻击和恶意软件感染。防火墙可以根据预定义的规则过滤流量&#xff0c;例如允许或阻止特定IP地址或端口的流量。它也可以检测和阻止恶意软件、病毒和其他威…

element-ui table sortable排序 掉后端接口方式

实例: 官方解释:如果需要后端排序&#xff0c;需将sortable设置为custom&#xff0c;同时在 Table 上监听sort-change事件&#xff0c;在事件回调中可以获取当前排序的字段名和排序顺序&#xff0c;从而向接口请求排序后的表格数据。 1.table上要加 sort-change"sortCha…

XTuner微调LLM:1.8B、多模态和Agent

XTuner微调大语言模型&#xff0c;我们的介绍主要分为以下六个方面。 首先我们讲一下Finetune&#xff1a;分为两种Finetune范式和一条数据的一生来讲解。 为什么要微调&#xff1f;我们的大语言模型为基座模型&#xff0c;要应用到某种特定的场景&#xff0c;需要微调做相应适…

STC8增强型单片机开发——C51版本Keil环境搭建

一、目标 了解C51版本Keil开发环境的概念和用途掌握C51版本Keil环境的安装和配置方法熟悉C51版本Keil开发环境的使用 二、准备工作 Windows 操作系统Keil C51 安装包&#xff08;可以从Keil官网下载&#xff09;一款8051单片机开发板 三、搭建流程 环境搭建的基本流程&#xf…
最新文章