FreeRTOS(二)任务基础知识

2023-05-16

一、前后台系统与RTOS 

  • 前后台系统 = 死循环(通常为1个) + 中断服务程序(通常为若干个)

  1. 应用程序是一个无限循环,循环中调用API函数完成所需的操作,这个大循环就叫做后台系统。
  2. 中断服务程序用于处理系统的异步事件,也就是前台系统。
  3. 前台是中断级,后台是任务级。

  • RTOS实时操作系统(软实时(不太严格) 硬实时(严格响应))

  1. 可剥夺型内核(任务调度器可以剥夺其他任务(优先级低)的CPU使用权
  2. 永远在运行处于就绪态的最高优先级的任务


二、FreeRTOS任务特性

  • 简单。
  • 无使用限制。
  • 支持抢占
  • 支持优先级
  • 每个任务都拥有堆栈导致了 RAM 使用量增大。
  • 如果使用抢占的话的必须仔细的考虑重入的问题

任务状态

任务优先级

  • 0 ~ configMAX_PRIORITIES-1       32个     31为系统时钟 0为空闲任务  故0、31一般不分配给用户任务
  • 数字越大,优先级越高(与ucos相反)
  • ucos最多有64个任务(包括系统任务和用户任务),

任务实现(代码的角度看——函数)

void vATaskFunction(void *pvParameters)
{
    for( ; ; )            
    {
        --任务应用程序--
        vTaskDelay();
    }
    vTaskDelete(NULL); 
}
  • 任务一般为一个死循环,故不能从任务函数中返回或者退出,从任务函数中返回或退出的话就会调用configASSERT(),前提是你定义了 configASSERT()。如果一定要从任务函数中退出的话那一定要调用函数 vTaskDelete(NULL)来删除此任务。 

任务控制块(记录任务属性,相当于身份证)

typedef struct tskTaskControlBlock
{
	volatile StackType_t	*pxTopOfStack;	/*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */

	#if ( portUSING_MPU_WRAPPERS == 1 )
		xMPU_SETTINGS	xMPUSettings;		/*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
	#endif

	ListItem_t			xStateListItem;	/*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
	ListItem_t			xEventListItem;		/*< Used to reference a task from an event list. */
	UBaseType_t			uxPriority;			/*< The priority of the task.  0 is the lowest priority. */
	StackType_t			*pxStack;			/*< Points to the start of the stack. */
	char				pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

	#if ( portSTACK_GROWTH > 0 )
		StackType_t		*pxEndOfStack;		/*< Points to the end of the stack on architectures where the stack grows up from low memory. */
	#endif

	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
		UBaseType_t		uxCriticalNesting;	/*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t		uxTCBNumber;		/*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
		UBaseType_t		uxTaskNumber;		/*< Stores a number specifically for use by third party trace code. */
	#endif

	#if ( configUSE_MUTEXES == 1 )
		UBaseType_t		uxBasePriority;		/*< The priority last assigned to the task - used by the priority inheritance mechanism. */
		UBaseType_t		uxMutexesHeld;
	#endif

	#if ( configUSE_APPLICATION_TASK_TAG == 1 )
		TaskHookFunction_t pxTaskTag;
	#endif

	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
		void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
	#endif

	#if( configGENERATE_RUN_TIME_STATS == 1 )
		uint32_t		ulRunTimeCounter;	/*< Stores the amount of time the task has spent in the Running state. */
	#endif

	#if ( configUSE_NEWLIB_REENTRANT == 1 )
		/* Allocate a Newlib reent structure that is specific to this task.
		Note Newlib support has been included by popular demand, but is not
		used by the FreeRTOS maintainers themselves.  FreeRTOS is not
		responsible for resulting newlib operation.  User must be familiar with
		newlib and must provide system-wide implementations of the necessary
		stubs. Be warned that (at the time of writing) the current newlib design
		implements a system-wide malloc() that must be provided with locks. */
		struct	_reent xNewLib_reent;
	#endif

	#if( configUSE_TASK_NOTIFICATIONS == 1 )
		volatile uint32_t ulNotifiedValue;
		volatile uint8_t ucNotifyState;
	#endif

	/* See the comments above the definition of
	tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
		uint8_t	ucStaticallyAllocated; 		/*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
	#endif

	#if( INCLUDE_xTaskAbortDelay == 1 )
		uint8_t ucDelayAborted;
	#endif

} tskTCB;

任务堆栈(保护工作环境)

//任务堆栈的变量类型为StackType_t,此变量类型如下:

#define portSTACK_TYPE uint32_t    //4个字节
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; 

//所以要注意,传给创建任务函数的堆栈数值大小×4才是真正的堆栈大小
  • 注意:传给创建任务函数的堆栈数值大小×4才是实际的堆栈大小 

 三、任务的创建与删除

  • 动态方法()

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"

#define START_STK_SIZE 120	//开始任务堆栈
#define START_TASK_PRIO 3	//开始任务优先级

#define TASK1_STK_SIZE 120	//任务1堆栈
#define TASK1_TASK_PRIO 2	//任务1优先级

#define TASK2_STK_SIZE 120	//任务2堆栈
#define TASK2_TASK_PRIO 1	//任务2优先级

void strat_task(void * pvParamemters);
void task1(void * pvParamemters);
void task2(void * pvParamemters);

TaskHandle_t StartTask_Handle;	//开始任务句柄
TaskHandle_t Task1Task_Handle;	//任务1句柄
TaskHandle_t Task2Task_Handle;	//任务2句柄

int main(void)
{
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 	 
	delay_init();	    				//延时函数初始化	  
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	xTaskCreate(	(TaskFunction_t) strat_task,	//
					(char *  	   ) "strat_task",
					(uint16_t	   ) START_STK_SIZE,
					(void *        ) NULL,
					(UBaseType_t   ) START_TASK_PRIO,
					(TaskHandle_t *) &StartTask_Handle );
	
    vTaskStartScheduler();          //开启任务调度
}
void strat_task(void * pvParamemters)    //创建task1和task2
{
	xTaskCreate(	(TaskFunction_t ) task1,
					(char *  		) "task1",
					(uint16_t		) TASK1_STK_SIZE,
					(void *			) NULL,
					(UBaseType_t	) TASK1_TASK_PRIO,
					(TaskHandle_t * ) &Task1Task_Handle );
	xTaskCreate(	(TaskFunction_t ) task2,
					(char *  		) "task2",
					(uint16_t		) TASK2_STK_SIZE,
					(void *			) NULL,
					(UBaseType_t	) TASK2_TASK_PRIO,
					(TaskHandle_t * ) &Task2Task_Handle );
	vTaskDelete(StartTask_Handle);
	//等价于vTaskDelete(NULL);删除自身
}

void task1(void * pvParamemters)
{
	while(1)
	{
		LED0 = !LED0;
		vTaskDelay(500);
	}
}
void task2(void * pvParamemters)
{
	while(1)
	{
		LED1 = !LED1;
		vTaskDelay(800);
	}
}

  • 静态方法()

  1. 使用静态方法的话需要将宏configSUPPORT_STATIC_ALLOCATION 设置为1

  2. 需要自己实现以下两个函数:

  3. void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, 
                            StackType_t **ppxIdleTaskStackBuffer, 
                            uint32_t *pulIdleTaskStackSize)    //空闲任务内存分配
    void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, 
                            StackType_t **ppxTimerTaskStackBuffer, 
                            uint32_t *pulTimerTaskStackSize)   //定时器任务内存分配

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "FreeRTOS.h"
#include "task.h"

//空闲任务任务堆栈
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
//空闲任务控制块
static StaticTask_t IdleTaskTCB;

//定时器服务任务堆栈
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
//定时器服务任务控制块
static StaticTask_t TimerTaskTCB;

//任务优先级
#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);

//任务优先级
#define TASK1_TASK_PRIO		2
//任务堆栈大小	
#define TASK1_STK_SIZE 		128  
//任务堆栈
StackType_t Task1TaskStack[TASK1_STK_SIZE];
//任务控制块
StaticTask_t Task1TaskTCB;
//任务句柄
TaskHandle_t Task1Task_Handler;
//任务函数
void task1_task(void *pvParameters);

//任务优先级
#define TASK2_TASK_PRIO		3
//任务堆栈大小	
#define TASK2_STK_SIZE 		128 
//任务堆栈
StackType_t Task2TaskStack[TASK2_STK_SIZE];
//任务控制块
StaticTask_t Task2TaskTCB;
//任务句柄
TaskHandle_t Task2Task_Handler;
//任务函数
void task2_task(void *pvParameters);


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

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

int main(void)
{
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 
	delay_init();	    				//延时函数初始化	 
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	
	
    //创建开始任务
	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();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建TASK1任务
	Task1Task_Handler=xTaskCreateStatic((TaskFunction_t	)task1_task,		
							(const char* 	)"task1_task",		
							(uint32_t 		)TASK1_STK_SIZE,	
							(void* 		  	)NULL,				
							(UBaseType_t 	)TASK1_TASK_PRIO, 	
							(StackType_t*   )Task1TaskStack,	
							(StaticTask_t*  )&Task1TaskTCB);	
    //创建TASK2任务
	Task2Task_Handler=xTaskCreateStatic((TaskFunction_t	)task2_task,		
							(const char* 	)"task2_task",		
							(uint32_t 		)TASK2_STK_SIZE,	
							(void* 		  	)NULL,				
							(UBaseType_t 	)TASK2_TASK_PRIO, 	
							(StackType_t*   )Task2TaskStack,	
							(StaticTask_t*  )&Task2TaskTCB);
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//task1任务函数
void task1_task(void *pvParameters)
{
	u8 task1_num=0;

	while(1)
	{
		task1_num++;	//任务执1行次数加1 注意task1_num1加到255的时候会清零!!
		LED0=!LED0;
		printf("任务1已经执行:%d次\r\n",task1_num);
		if(task1_num==5) 
		{
			if(Task2Task_Handler != NULL)		//任务2是否存在?	
			{
				vTaskDelete(Task2Task_Handler);	//任务1执行5次删除任务2
				Task2Task_Handler=NULL;			//任务句柄清零
				printf("任务1删除了任务2!\r\n");
			}
		}
        vTaskDelay(1000);              //延时1s,也就是1000个时钟节拍	
	}
}

//task2任务函数
void task2_task(void *pvParameters)
{
	u8 task2_num=0;
	
	while(1)
	{
		task2_num++;	//任务2执行次数加1 注意task1_num2加到255的时候会清零!!
        LED1=!LED1;
		printf("任务2已经执行:%d次\r\n",task2_num);
        vTaskDelay(1000);             //延时1s,也就是1000个时钟节拍	
	}
}


四、任务的挂起与恢复

 

 

 

 

 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS(二)任务基础知识 的相关文章

  • 【FreeRtos学习笔记】STM32 CubeMx——Timers(定时器)

    目录 1 软件定时器 2 示例程序 2 1 例程功能 2 2 步骤 2 3 实验结果 2 4 函数讲解 1 软件定时器 定时器是MCU常用的外设 我们在学习各种单片机时必然会学习它的硬件定时器 但是 MCU自带的硬件定时器资源是有限的 而且
  • FreeRTOS记录(七、FreeRTOS信号量、事件标志组、邮箱和消息队列、任务通知的关系)

    我们在前面单独介绍过FreeRTOS的任务通知和消息队列 但是在FreeRTOS中任务间的通讯还有信号量 邮箱 事件组标志等可以使用 这篇文章就这些成员与消息队列和任务通知的关系进行说明分析 增加邮箱部分 任务通知发送消息 Demo 202
  • 一文教你学会keil软件仿真

    仿真在我们调试代码中是非常重要的 通过仿真 我们可以快速定位到错误代码 或者错误逻辑的地方 这里我就以上一篇博客为例 教大家如何软件仿真 软件仿真不需要单片机 直接通过keil软件进行代码调试 一 打开工具 二 选择软件仿真 三 开始仿真
  • FreeRTOS学习(八) 延时函数

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 FreeRTOS延时函数有两个 分别是 vTaskDelay vTaskDelayUntil 1 vTaskDelay 任务相对延时 函数原型
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • freertos————互斥锁

    线程安全 多线程程序处于一个多变的环境 可访问的全局变量和堆数据随时可能被其他的线程改变 多个线程同时访问一个共享数据 可能造成严重的后果 出现问题的是之前移植了一个freemodbus的从站 多个任务访问全局变量保持寄存器区 导致最后读出
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • FreeRTOS之事件

    FreeRTOS之事件 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 一 事件定义 事件 事件集 与高数上的集合意义差不多 事件啊 其实是实现任务间通信的机制 主要用于实现多任务间的同步 但是事件类型
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • [FreeRTOS入门学习笔记]定时器

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • FreeRTOS学习---“定时器”篇

    总目录 FreeRTOS学习 任务 篇 FreeRTOS学习 消息队列 篇 FreeRTOS学习 信号量 篇 FreeRTOS学习 事件组 篇 FreeRTOS学习 定时器 篇 FreeRTOS提供了一种软件定时器 用来快速实现一些周期性的
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v
  • 如何将 void* 转换为函数指针?

    我在 FreeRTOS 中使用 xTaskCreate 其第四个参数 void const 是传递给新线程调用的函数的参数 void connect to foo void const task params void on connect
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J

随机推荐

  • 单片机对底层寄存器的操作

    最近项目用到了国产的一款单片机 xff0c 没有例程的支持 xff0c 需要自己从头开始写底层 又感受到了自己本科刚学习51的时候的浮躁 xff0c 不懂得如何操作底层的寄存器 xff0c 只是一味的抄写别人的例程 xff0c 然后进行简单
  • PyQt5自学记录(1)——PyQt5多线程实现详解

    PyQt5自学记录 xff08 1 xff09 PyQt5中多线程实现详解 最近想用PyQt5完成图像识别的一个GUI系统 xff0c 在调用算法模型进行识别的时候 xff0c 界面会卡住没有反应 xff0c 所以想学习一下多线程解决这个问
  • 编写程序的步骤

    编写 C 语言程序的7个步骤 1 定义程序的目标 资深程序员需要养成的良好的思考习惯 在动手写程序之前 xff0c 要在脑中有清晰的思路 想要程序去做什么 1 首先自己要明确自己想做什么 xff0c 2 思考你的程序需要哪些信息 xff0c
  • 看懂英文数据手册、搭建电路

    阅读数据手册是一个工程师的必备技能 xff0c 拿到一份数据手册 xff0c 特别是英文数据手册 xff0c 如何去读 xff0c 才能更快更好的找到自己想要的东西 xff1f 坚信 xff1a 阅读英文手册 xff0c 并没有想象的那么难
  • 英语四级重点短语

    devote to 将 致力于 derive from 61 originate from 61 stem from 源自于 instant adj 立即的 速溶的 instant coffee速溶咖啡 instant noodle 方便面
  • stm32串口通信的一个小总结(从底层进行理解)

    从底层理解stm32USART串口通信 以前学串口通信踩过很多坑 xff0c 过了一段时间又有些忘了 xff0c 现在问了几个很强很强的人差不多弄懂了 xff0c 现在写一写总结 xff0c 免得以后又忘了 基本知识 xff1a 1 TDR
  • 旋翼回收火箭系列博客3——控制系统设计(PX4火箭)

    绪论 为了缩短研制周期和提高产品可靠性 xff0c 本系统采用商用开源自动驾驶仪PX4 xff0c 实现旋翼空中展开并回收的功能 PX4是全球最为成熟的开源自动驾驶仪 xff0c 可实现自动起飞 降落 执行航点等基本任务 然而此次火箭比赛要
  • 创建进程的系统调用

    Unix采用fork exec两个系统调用来完成新进程的创建 fork 创建调用该命令的进程的副本 子进程与父进程几乎处处相同 xff0c fork后两个进程执行的程序是一样的 xff0c id不一样 xff0c 相应变量就不一致 xff0
  • vscode解决git提交冲突

    我的场景 xff1a master分支在一台电脑上被修改提交到远程后 xff0c 在另一台电脑上没有拉取远程更改 xff0c 也进行了更改提交 点击vscode看到合并冲突文件为index js 点击查看冲突如下 有颜色的是冲突位置代码 x
  • LZW压缩算法(数据无损压缩)

    目录 一 LZW算法介绍 二 算法介绍 1 LZ xff37 算法的基本概念 2 LZW压缩的基本原理 3 LZW算法流程 xff1a 零 常用无损数据压缩算法 字典算法 游程编码 基于字典编码技术的LZW算法 基于哈夫曼编码原理的压缩算法
  • sftp账号创建和权限设置

    操作前需先开启telnet服务 xff0c 防止修改sshd config后 xff0c sshd服务启不了 systemctl span class token keyword start span telnet span class t
  • Python【列表】

    文章目录 1 列表的方法及注释2 其他修改列表的办法2 列表推导式3 列表的切片4 列表转换4 1 字符串转列表 xff1a 4 2 列表转字符串 list 列表 是一个可变序列 1 列表的方法及注释 列表的方法注释append x 将元素
  • FTP的port模式和pasv模式

    FTP的port模式和pasv模式 FTP具有两种模式 xff0c 分别是port模式 也叫主动模式 和pasv模式 也叫被动模式 主动模式 主动模式的FTP是指服务器主动连接客户端的数据端口 xff0c 可以理解为服务端主动给客户端传输文
  • shell for循环多个变量

    1 使用花括号 var1 var2 var3 a 61 span class token string 34 apple 34 span span class token punctuation span b 61 span class t
  • shell 基本运算符

    文章目录 1 算数运算2 关系运算符3 布尔运算符4 逻辑运算符5 字符串运算符6 文件测试运算符知识点 1 算数运算 方法一 sum1 61 96 expr 3 span class token operator 43 span 5 96
  • Dockerfile简介

    1 什么是dockerfile Dockerfile是一个包含用于组合映像的命令的文本文档 可以使用在命令行中调用任何命令 Docker通过读取Dockerfile中的指令自动生成映像 docker build命令用于从Dockerfile
  • 容器通信之跨链接通信

    前言 同一主机下搭建容器应用栈的环境 xff0c 只需要完成容器互联来实现容器间的通信即可 xff0c 这里采用docker run link选项建立容器间的互联关系 docker官方已不推荐使用docker run link来链接2个容器
  • Linux进程间通信

    1 unix域套接字 域套接字 xff1a 1 只能用于同一设备上不同进程之间的通信 xff1b 2 效率高于网络套接字 域套接字仅仅是复制数据 xff0c 并不走协议栈 xff1b 3 可靠 xff0c 全双工 xff1b 2 IP套接字
  • 什么是API

    1 什么是API API是Application Programming Interface xff08 应用程序接口 xff09 的缩写 是一些预先定义的函数 xff0c 目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力
  • FreeRTOS(二)任务基础知识

    一 前后台系统与RTOS 前后台系统 61 死循环 xff08 通常为1个 xff09 43 中断服务程序 xff08 通常为若干个 xff09 应用程序是一个无限循环 xff0c 循环中调用 API 函数完成所需的操作 xff0c 这个大