FreeRTOS-任务通知源码分析

2023-05-16

任务通知可用来代替信号量、消息队列、事件标志位,而且使用任务通知的形式效率会更高,它不需要像信号量那样创建队列和操作队列,任务通知的存储变量来自任务控制块中,当宏 configUSE_TASK_NOTIFICATIONS 被定义为1时就可以使用任务通知相关的函数了。任务通知的接口函数同样存在发送和接收,发送的接口函数如下:

/* 发送通知,有通知值但不保留接收任务原通知值 */
xTaskNotify( xTaskToNotify, ulValue, eAction )
xTaskNotifyFromISR(xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken)

/* 发送通知(可代替计数型信号量),没有通知值并且不保留接收任务的通知值,会将接收任务的通知值加一 */
xTaskNotifyGive(xTaskToNotify)
vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )

/* 发送通知,有通知值并且保留接收任务的原通知值 */
xTaskNotifyAndQuery(xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue)
xTaskNotifyAndQueryFromISR(xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken)

这几个发送通知的接口实际上都是宏,定义如下:

#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL )
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )

#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL )
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )

有分任务之间的接口和中断的接口,核心主要就是这两个函数:

	BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
	BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )

任务通知的写入方式有以下几种,使用一个枚举来定义:

typedef enum
{
	eNoAction = 0,				/* 不升级通知值 */
	eSetBits,					/* 更新指定的bit */
	eIncrement,					/* 通知值加一 */
	eSetValueWithOverwrite,		/* 覆写的方式更新通知值 */
	eSetValueWithoutOverwrite	/* 不覆盖通知值 */
} eNotifyAction;

xTaskGenericNotify 通用通知函数的源码分析如下:

#if( configUSE_TASK_NOTIFICATIONS == 1 )

	/* 形参:
	 * 	xTaskToNotify:任务句柄(要通知的任务)
	 * 	ulValue:任务通知值
	 * 	eAction:任务通知更新的方法
	 * 	pulPreviousNotificationValue:用于保存任务更新前的任务通知值
	 */
	BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
	{
	TCB_t * pxTCB;
	BaseType_t xReturn = pdPASS;
	uint8_t ucOriginalNotifyState;

		configASSERT( xTaskToNotify );
		pxTCB = xTaskToNotify;

		/* 进入临界区 */
		taskENTER_CRITICAL();
		{
			if( pulPreviousNotificationValue != NULL )
			{
				/* 形参作为返回值,返回值空间有效,返回任务的原通知值 */
				*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
			}

			/* 获取被通知任务原来的状态 */
			ucOriginalNotifyState = pxTCB->ucNotifyState;

			/* 更新被通知任务的状态为接收 */
			pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;

			/* 判断任务通知的更新方法 */
			switch( eAction )
			{
				case eSetBits	:
					/* 用做二值信号量 */
					pxTCB->ulNotifiedValue |= ulValue;
					break;

				case eIncrement	:
					/* 用做计数型信号量 */
					( pxTCB->ulNotifiedValue )++;
					break;

				case eSetValueWithOverwrite	:
					/* 覆写的方式写入数据 */
					pxTCB->ulNotifiedValue = ulValue;
					break;

				case eSetValueWithoutOverwrite :
					/* 不覆盖方式写入数据 */
				
					if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
					{
						/* 被通知任务的状态不处于接收状态的话直接赋值 */
						pxTCB->ulNotifiedValue = ulValue;
					}
					else
					{
						/* 如果任务处于接收状态的话就不能被写入,因为使用的不覆写的方式,返回错误 */
						xReturn = pdFAIL;
					}
					break;

				case eNoAction:
					break;

				default:
					configASSERT( pxTCB->ulNotifiedValue == ~0UL );

					break;
			}

			traceTASK_NOTIFY();

			/* 如果被通知任务原来的状态为等待通知而进入阻塞,这里解锁阻塞 */
			if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
			{
				/* 将任务从原来的状态列表中移除 */
				( void ) uxListRemove( &( pxTCB->xStateListItem ) );
				/* 将任务添加到就绪列表中 */
				prvAddTaskToReadyList( pxTCB );

				configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );

				#if( configUSE_TICKLESS_IDLE != 0 )
				{
					prvResetNextTaskUnblockTime();
				}
				#endif

				/* 如果任务的优先级高于当前优先级则进行一次任务切换 */
				if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
				{
					taskYIELD_IF_USING_PREEMPTION();
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		/* 退出临界区 */
		taskEXIT_CRITICAL();

		return xReturn;
	}

#endif /* configUSE_TASK_NOTIFICATIONS */

在中断中使用的发送函数 xTaskGenericNotifyFromISR 分析如下:

#if( configUSE_TASK_NOTIFICATIONS == 1 )

	/* 形参:
	 * 	xTaskToNotify:任务句柄
	 * 	ulValue:任务通知值
	 * 	eAction:任务通知更新的方法
	 * 	pulPreviousNotificationValue:用于保存任务更新前的任务通知值
	 *	pxHigherPriorityTaskWoken:使用变量记退出此函数以后是否进行任务切换,用于需要提供一个变量来保存这个值
	 */
	BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
	{
	TCB_t * pxTCB;
	uint8_t ucOriginalNotifyState;
	BaseType_t xReturn = pdPASS;
	UBaseType_t uxSavedInterruptStatus;

		configASSERT( xTaskToNotify );

		portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
		pxTCB = xTaskToNotify;

		/* 进入中断临界区 */
		uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
		{
			if( pulPreviousNotificationValue != NULL )
			{
				/* 形参作为返回值,返回值空间有效,返回任务的原通知值 */
				*pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
			}

			/* 获取被通知任务原来的状态 */
			ucOriginalNotifyState = pxTCB->ucNotifyState;
			/* 更新被通知任务的状态为接收 */
			pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;

			/* 判断任务通知的更新方法 */
			switch( eAction )
			{
				case eSetBits	:
					/* 用做二值信号量 */
					pxTCB->ulNotifiedValue |= ulValue;
					break;

				case eIncrement	:
					/* 用做计数型信号量 */
					( pxTCB->ulNotifiedValue )++;
					break;

				case eSetValueWithOverwrite	:
					/* 覆写的方式写入数据 */
					pxTCB->ulNotifiedValue = ulValue;
					break;

				case eSetValueWithoutOverwrite :
					/* 不覆盖方式写入数据 */
				
					if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
					{
						/* 被通知任务的状态不处于接收状态的话直接赋值 */
						pxTCB->ulNotifiedValue = ulValue;
					}
					else
					{
						/* 如果任务处于接收状态的话就不能被写入,返回错误 */
						xReturn = pdFAIL;
					}
					break;

				case eNoAction :
					break;

				default:
					configASSERT( pxTCB->ulNotifiedValue == ~0UL );
					break;
			}

			traceTASK_NOTIFY_FROM_ISR();

			/* 如果被通知任务原来的状态为等待通知而进入阻塞,这里解锁阻塞 */
			if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
			{
				configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );

				/* 如果调度器休眠没休眠,执行这个分支 */
				if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
				{
					/* 将任务从原来的状态列表中移除 */
					( void ) uxListRemove( &( pxTCB->xStateListItem ) );
					/* 将任务添加到就绪列表中 */
					prvAddTaskToReadyList( pxTCB );
				}
				/* 如果调度器休眠了,执行这个分支 */
				else
				{
					/* 将任务插入到挂机就绪列表,调度器恢复后再放入就绪列表 */
					vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
				}

				/* 如果任务的优先级高于当前优先级则进行一次任务切换 */
				if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
				{
					if( pxHigherPriorityTaskWoken != NULL )
					{
						/* 返回告知需要进行一次任务切换 */
						*pxHigherPriorityTaskWoken = pdTRUE;
					}
					xYieldPending = pdTRUE;
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
		}
		/* 退出中断临界区 */
		portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );

		return xReturn;
	}

#endif

下面获取任务通知的接口:

/* 获取任务通知,可以设置在退出此函数的时候将任务通知值清零或减一,用于代替二值信号和计数型信号量 */
ulTaskNotifyTake(BaseType_t xClearCountOnExit, TickType_t xTicksToWait)

/* 获取任务通知,等待任务通知,比ulTaskNotifyTake强大,全功能版任务通知获取函数 */
xTaskNotifyWait(xTaskToNotify, ulValue, eAction)

ulTaskNotifyTake 的源码分析如下:

#if( configUSE_TASK_NOTIFICATIONS == 1 )

	/* 形参:
	 * 	xClearCountOnExit:为 pdFALSE 的话在退出时通知值减一,类似计数型信号量,
	 *					   为 pdTURE 的话在退出时通知值清零,类似二值信号量
	 * 	xTicksToWait:阻塞时间
	 */
	uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
	{
	uint32_t ulReturn;

		/* 进入临界区 */
		taskENTER_CRITICAL();
		{
			/* 如果当前任务通知值为0 */
			if( pxCurrentTCB->ulNotifiedValue == 0UL )
			{
				/* 任务的通知状态标记为等待通知 */
				pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;

				/* 如果任务的等待时间大于0 */
				if( xTicksToWait > ( TickType_t ) 0 )
				{
					/* 将任务添加到延时任务列表 */
					prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
					traceTASK_NOTIFY_TAKE_BLOCK();

					/* 进行一次任务调度 */
					portYIELD_WITHIN_API();
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		/* 退出临界区 */
		taskEXIT_CRITICAL();

		/* 进入临界区,执行到这里说明接收到了来自其它任务的通知或超时 */
		taskENTER_CRITICAL();
		{
			traceTASK_NOTIFY_TAKE();
			/* 获取当前任务的通知值 */
			ulReturn = pxCurrentTCB->ulNotifiedValue;

			/* 通知值不为0 */
			if( ulReturn != 0UL )
			{
				if( xClearCountOnExit != pdFALSE )
				{
					/* 类似二值信号量,获取到后清零 */
					pxCurrentTCB->ulNotifiedValue = 0UL;
				}
				else
				{
					/* 类似计数信号量,获取到后减一 */
					pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
			/* 当前任务的通知状态改为等待通知 */
			pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
		}
		/* 退出临界区 */
		taskEXIT_CRITICAL();

		return ulReturn;
	}

#endif

xTaskNotifyWait 源码分析如下:

#if( configUSE_TASK_NOTIFICATIONS == 1 )

	/* 形参:
	 *	ulBitsToClearOnEntry:进入函数时是否清除任务bit,没接收到任务通知的时候将任务
	 *						  通知值与此参数的取反值进行按位与运算,当此参数
	 *						  为0xffffffff时会将任务的通知值清零
	 * 	xClearCountOnExit:为 pdFALSE 的话在退出时通知值减一,类似计数型信号量,
	 *					   为 pdTURE 的话在退出时通知值清零,类似二值信号量
	 *	pulNotificationValue:用于保存任务通知值
	 * 	xTicksToWait:阻塞时间
	 */
	BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
	{
	BaseType_t xReturn;

		/* 进入临界区 */
		taskENTER_CRITICAL();
		{
			/* 当前任务的通知状态不是接收状态,即还没接收到任务通知 */
			if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
			{
				/* 清除指定的bit */
				pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;

				/* 任务的通知状态标记为等待通知 */
				pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;

				/* 用户设置的超时时间大于0 */
				if( xTicksToWait > ( TickType_t ) 0 )
				{
					/* 将任务添加到延时列表中 */
					prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
					traceTASK_NOTIFY_WAIT_BLOCK();

					/* 进行一次任务调度 */
					portYIELD_WITHIN_API();
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		/* 退出临界区 */
		taskEXIT_CRITICAL();
		
		/* 进入临界区,执行到这里说明接收到了来自其它任务的通知或超时 */
		taskENTER_CRITICAL();
		{
			traceTASK_NOTIFY_WAIT();

			/* 用户传入的用于保存通知值的变量不为空 */
			if( pulNotificationValue != NULL )
			{
				/* 返回任务当前通知值 */
				*pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
			}

			/* 未接收到任务通知返回 pdFALSE */
			if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )			{

				xReturn = pdFALSE;
			}
			/* 接收到任务通知返回 pdTRUE */
			else
			{
				/* 清除指定的bit */
				pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
				xReturn = pdTRUE;
			}
			/* 任务的通知状态标记为等待通知 */
			pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
		}
		/* 退出临界区 */
		taskEXIT_CRITICAL();

		return xReturn;
	}

#endif 

关于任务通知的代码相对比较简单,都是通过直接赋值的形式,不存在像信号量那样的入队和出队过程。

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

FreeRTOS-任务通知源码分析 的相关文章

  • UCOSII里面为什么调用OS_ENTER_CRITICAL()或OS_EXIT_CRITICAL()会出错,出错信息为:undeclared identifier `cpu_sr‘

    可以观察到OSTickISR Init 函数内部调用了OS ENTER CRITICAL 和OS EXIT CRITICAL 并且 1 该OSTickISR Init 函数所在的 C文件包含了includes h文件 include inc
  • 心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

    文章目录 前言 介绍 系统框架 原项目地址 本项目开发开源地址 硬件PCB 软件功能 详细内容 硬件外壳制作 WS2812级联及控制 MAX30102血氧传感器 0 96OLED FreeRTOS 效果视频 总结 前言 在好几年前 我好像就
  • 基于HAL库的FREERTOS----------二.任务API函数

    任务API函数览概 CUBEMX对 做了API的封装 很多 的函数没有封装到位 可以用原函数调用 任务API函数分别介绍 1 uxTaskPriorityGet 此函数用来获取指定任务的优先级 要使用此函数的话宏 INCLUDE uxTas
  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • FreeRTOS学习笔记 6 - 互斥量

    目录 1 创建 2 获取 3 释放 4 测试 FreeRTOS不支持调度方式的设置 所以下面2个宏定义可以随意设置值 define RTOS IPC FLAG FIFO 0x00 define RTOS IPC FLAG PRIO 0x01
  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能
  • ZYNQ中FreeRTOS中使用定时器

    使用普通的Timer中断方式时 Timer中断可以正常运行 但是UDP通信进程无法启动 其中TimerIntrHandler是中断服务程序 打印程序运行时间与从BRAM中读取的数据 void SetupInterruptSystem XSc
  • Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory (referred from tasks.o).

    我用的是F103ZET6的板子 移植成功后 编译出现两个错误是关于stm32f10x it c 里 void SVC Handler void void PendSV Handler void 两个函数的占用问题 随后编译出现以下两个问题
  • 基于HAL库的FREERTOS-----------三.队列

    一 队列简介 在实际的应用中 常常会遇到一个任务或者中断服务需要和另外一个任务进行 沟通交流 这个 沟通交流 的过程其实就是消息传递的过程 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式 但是如果在使用操作系统的应用中用
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS之事件

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

    打开啊哈C 新建一个程序输出hello world include
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • 13-FreeRTOS任务创建与删除

    任务创建和删除API函数位于文件task c中 需要包含task h头文件 task h里面包函数任务的类型函数 例如 对xTaskCreate的调用 通过指针方式 返回一个TaskHandle t 变量 然后可将该变量用vTaskDele
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来

随机推荐

  • 【做题系统】后端设计

    目录 一 设计思路 1 项目背景 2 技术栈选择 二 系统设计 1 系统结构图 2 项目结构 3 数据建模 4 数据流图 5 主要流程图 三 问题及解决办法 1 实现安全登录 访问 2 数据库中的信息安全问题 3 Mybatis plus如
  • C/C++字符串查找函数

    C C 43 43 string库 xff08 string h xff09 提供了几个字符串查找函数 xff0c 如下 xff1a memchr在指定内存里定位给定字符strchr在指定字符串里定位给定字符strcspn返回在字符串str
  • ssh命令-manpage

    SSH Section User Commands 1 Index Return to Main Contents BSD mandoc NAME ssh OpenSSH SSH 客户端 远程登录程序 总览 SYNOPSIS ssh l l
  • 一小时做出Java实战项目——飞翔的小鸟

    学姐又来啦 xff0c 今日分享一个Java实战项目 飞翔的小鸟 相信大家都玩过这个游戏 xff0c 这个游戏陪伴了我们整整一个童年 xff0c 是我们青春的回忆 飞翔的小鸟 xff0c 游戏中玩家只需通过点击方向键操纵让小鸟避开绿色管道等
  • 搭建本地仓库源

    一 如何搭建仓库源 之前讲了定制ISO的方法 xff1a 使用chroot定制系统 xff0c 但有时候我们想自定义的安装包不在上游的仓库源中 xff0c 在我们本地应该怎么办呢 xff1f 如果我们将deb包拷贝到iso目录再安装有点过于
  • 节点操作案例

    1 下拉菜单 xff08 仿微博 xff09 lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt me
  • document获取对象的三种三方法

    Document对象中有几个常用的方法 xff0c 我们在Dom简介中提到过 说到获取JavaScript对象的方法 xff0c 最常用的可能就是getElementById了 xff0c 它是Document中最常用的获取对象的方式之一
  • 程序员,最关键的跨越是什么?做到了月薪可能翻上几番~

    黑马程序员视频库 播妞微信号 xff1a boniu236 传智播客旗下互联网资讯 学习资源免费分享平台 作为一名程序员 xff0c 最关键的跨越是什么 xff1f 从普通程序员进阶为熟练开发者 xff0c 从熟练开发者跃升到技术专家或架构
  • 黑马程序员:3分钟带你读懂C/C++学习路线

    随着互联网及互联网 43 深入蓬勃的发展 xff0c 经过40余年的时间洗礼 xff0c C C 43 43 俨然已成为一门贵族语言 xff0c 出色的性能使之成为高级语言中的性能王者 而在今天 xff0c 它又扮演着什么样重要的角色呢 x
  • 数据归一化

    原文链接 xff1a 从公式出发 xff1a 什么是模型收敛的有效方法 xff1f 大家好 xff0c 我是泰哥 数据归一化在模型收敛中起着至关重要的作用 xff0c 从经典机器学习到深度学习的数据归一化方法是如何一步步演变的呢 xff1f
  • 【Python面试】 说说Python变量、函数、类的命名规则?

    最近公众号新增加了一个栏目 xff0c 就是每天给大家解答一道Python常见的面试题 xff0c 反正每天不贪多 xff0c 一天一题 xff0c 正好合适 xff0c 只希望这个面试栏目 xff0c 给那些正在准备面试的同学 xff0c
  • ​LeetCode刷题实战46:全排列

    算法的重要性 xff0c 我就不多说了吧 xff0c 想去大厂 xff0c 就必须要经过基础知识和业务逻辑面试 43 算法面试 所以 xff0c 为了提高大家的算法能力 xff0c 这个公众号后续每天带大家做一道算法题 xff0c 题目就从
  • Android硬件访问服务-Service

    Android有四大组件 xff1a 一 Activity 二 Service 三 Broadcast Receiver 四 Content Provider Service是Android中一个类 xff0c 它是Android四大组件之
  • android6.0第三方APP获得设备节点的访问权限

    之前使用android4 4的系统进行开发时 system app xff08 系统自带APP xff09 目录下的 app 可以直接访问 dev 目录下的设备节点 xff0c Android 5 0 以后 xff0c 因为采取了 SEAn
  • U-boot取消或修改启动延时bootdelay

    在我们的实际项目中都希望uboot尽量能够快速启动 xff0c 这就涉及到uboot的裁剪工作 xff0c 由于裁剪的工作量和内容比较多 xff0c 这里暂不描述 但是uboot有个启动延时bootdelay xff0c 在我们进入linu
  • uboot启动分析第一阶段(start.S)

    前面分析了启动脚本 Makefile mkconfig xff0c 接下来就是uboot的start S这个启动代码了 xff0c 下面是本章的平台介绍 xff1a 单板 xff1a 迅为4412开发板 Exynos 4412 SDRAM
  • Android使用串口(基于android-serialport-api)

    运行平台 xff1a CPU xff1a 全志V40 Android版本 xff1a 6 0 1 关于安卓设备上使用串口 xff0c 谷歌官方在github上有提供代码实例 xff0c 里面有JNI的代码和串口API的java文件 xff0
  • FreeRTOS-启动任务调度器源码分析

    本章基于FreeRTOS的启动任务调度器源码分析 xff0c 后续将会上传其它我对FreeRTOS的源码分析过程及理解 xff0c 首先来认识一下任务调度器 任务调度器 xff1a 任务调度器主要用于实现任务的切换 xff0c 任务并不是我
  • FreeRTOS-任务创建源码分析

    任务创建是FreeRTOS系统启动的第一个步骤 xff0c 前面在启动调度器的时候先创建了空闲任务 xff0c 然后再由调度器跳到任务里面去执行 任务创建函数里面做了很多的工作 xff0c 先会为任务堆栈和任务控制块分配内存并初始化它们 x
  • FreeRTOS-任务通知源码分析

    任务通知可用来代替信号量 消息队列 事件标志位 xff0c 而且使用任务通知的形式效率会更高 xff0c 它不需要像信号量那样创建队列和操作队列 xff0c 任务通知的存储变量来自任务控制块中 xff0c 当宏 configUSE TASK