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

个人做网站被骗抖音推广怎么做

个人做网站被骗,抖音推广怎么做,网站里怎么做301指向,甘德县wap网站建设公司1. 队列简介 1.1 队列的概念 队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递) 类似全局变量?假设有一个全局变量a 0,现有两个任务都在写这个变量 a: 大家想象一下如果任务 1 运行一次&#…

1. 队列简介

1.1 队列的概念

队列是任务到任务、任务到中断、中断到任务数据交流的一种机制(消息传递)

类似全局变量?假设有一个全局变量a = 0,现有两个任务都在写这个变量 a:

在这里插入图片描述
大家想象一下如果任务 1 运行一次,任务 2 运行一次,理论上 a 等于什么?等于 2。但是大家想象一下,这个 a++ 在 C 语言这里其实它内部是分成很多个操作的,我们来看一下,内部首先就把 a 给读到 cpu 的寄存器 r0 里面,然后再把 r0 进行加一,然后加完之后,再把 r0 这个值给回这个 a 这个地址,这样的话 a 就变成 1 了,如果裸机的话,肯定是没有这种任务1、任务2 去干扰你。
但是 os 的话就存在这种可能了,比如任务 1 执行到第二步这里的时候被更高优先级的任务 2 给打断了,这时候有可能出现什么情况?那么假设一下,首先 a 本来是 0,读到 r0 里面,此时 r0 = r0 + 1 = 1,此时被任务 2 打断,那打断之后代表 r0 还没给到 a;那这时候任务 2 它同样的也是这么一个操作,因为任务 2 的优先级是最高的,所以它完整的执行了这 3 步,这时候 a 它还是 0,因为任务 1 还没有执行到第三步,还没给回 a,所以执行完这 3 步以后,a = 1,然后任务 2 执行完之后又回到任务 1 的第三步,那这时候 r0 它也是 1,1 它又赋值给 a,这时候它们运行的结果 a 就等于 1。
那这样的话执行了两个任务,都执行了一次,但是它实际的效果竟然 a = 1,这样就造成一个数据的受损。

全局变量的弊端:数据无保护,导致数据不安全,当多个任务同时对该变量操作时,数据易受损。

使用队列的情况如下:
在这里插入图片描述

本质:临界区->关中断->关闭优先级最低的 PendSV 中断->关闭任务调度。

队列的优点:读写队列做好了保护,防止多任务同时访问冲突;我们只需要直接调用API函数即可,简单易用!

FreeRTOS基于队列, 实现了多种功能,其中包括队列集、互斥信号量、计数型信号量、二值信号量、 递归互斥信号量,因此很有必要深入了解 FreeRTOS 的队列 。

1.2 队列的特征

在队列中可以存储数量有限、大小固定的数据。队列中的每一个数据叫做“队列项目”,队列能够存储“队列项目”的最大数量称为队列的长度。

类似于数组。

在这里插入图片描述

注意:在创建队列时,就要指定队列长度以及队列项目的大小!

FreeRTOS 队列特点

  1. 数据入队出队方式:队列通常采用 “先进先出”(FIFO) 的数据存储缓冲机制,即先入队的数据会先从队列中被读取,FreeRTOS中也可以配置为 “后进先出”(LIFO) 方式;
  2. 数据传递方式。FreeRTOS中队列采用实际值传递,即将数据拷贝到队列中进行传递。FreeRTOS采用拷贝数据传递,也可以传递指针,所以在传递较大的数据的时候采用指针传递。(像 ucos 是指针传递,把地址给写进去)

优点:互不干扰。
缺点:耗时比较长。

  1. 多任务访问。队列不属于某个任务,任何任务和中断都可以向队列发送/读取消息。
  2. 出队、入队阻塞。当任务向一个队列发送消息时,假设此时当队列已满无法入队,这时候就可以指定一个阻塞时间。
  1. 若阻塞时间为 0 :直接返回不会等待;
  2. 若阻塞时间为 0~port_MAX_DELAY :等待设定的阻塞时间,若在该时间内还无法入队,超时后直接返回不再等待;
  3. 若阻塞时间为 port_MAX_DELAY :死等,一直等到可以入队为止。出队阻塞与入队阻塞类似;
  • 入队阻塞:
    在这里插入图片描述

队列满了,此时写不进去数据;
① 将该任务的状态列表项挂载在 pxDelayedTaskList(阻塞列表);
② 将该任务的事件列表项挂载在 xTasksWaitingToSend(等待发送列表);

  • 出队阻塞:
    在这里插入图片描述
    队列为空,此时读取不了数据;
    ①将该任务的状态列表项挂载在 pxDelayedTaskList(阻塞列表);
    ②将该任务的事件列表项挂载在 xTasksWaitingToReceive(等待接收列表);

问题:当多个任务写入消息给一个“满队列”时,这些任务都会进入阻塞状态,也就是说有多个任务在等待同一个队列的空间。那当队列中有空间时,哪个任务会进入就绪态?

答:

  1. 优先级最高的任务
  2. 如果大家的优先级相同,那等待时间最久的任务会进入就绪态

1.3 队列基本操作过程

在这里插入图片描述
在这里插入图片描述
这时候这个 20 它会移到队列头部。

2. 队列结构体介绍

队列实际它的内存是分为两部分,第一个就是存放结构体的内存,接着是队列里面的队列项,它用来存放数据的,我们写入数据给队列就写入到队列项里面了。

typedef struct QueueDefinition 
{int8_t * pcHead							/* 存储区域的起始地址(队列项的起始地址) */int8_t * pcWriteTo;        				/* 下一个写入的位置 */union									/* 当把这个结构体用作不同的功能的时候,联合体的作用是不一样的 */{QueuePointers_t     xQueue; 		/* 当用作队列的时候,就使用的上面这个 */SemaphoreData_t  xSemaphore; 		/* 当用作互斥信号量的时候,就使用的下面这个 */} u ;List_t xTasksWaitingToSend; 			/* 等待发送列表 */List_t xTasksWaitingToReceive;			/* 等待接收列表 */volatile UBaseType_t uxMessagesWaiting; /* 非空闲队列项目的数量 */UBaseType_t uxLength;					/* 队列长度 */UBaseType_t uxItemSize;                 /* 队列项目的大小 */volatile int8_t cRxLock; 				/* 读取上锁计数器 */volatile int8_t cTxLock;				/* 写入上锁计数器 *//* 其他的一些条件编译 */
} xQUEUE;

上锁计数器:当锁住队列的时候,此时还是可以正常读写队列的,只不过操作不了它的等待发送和等待接收这两个列表;当解锁的时候,才会去操作这两个列表。那这个就叫队列锁。

当用于队列使用时:

typedef struct QueuePointers
{int8_t * pcTail; 					/* 存储区的结束地址 */int8_t * pcReadFrom;				/* 最后一个读取队列的地址 */
} QueuePointers_t;

当用于互斥信号量和递归互斥信号量时 :

typedef struct SemaphoreData
{TaskHandle_t xMutexHolder;			/* 互斥信号量持有者 */UBaseType_t uxRecursiveCallCount;	/* 递归互斥信号量的获取计数器 */
} SemaphoreData_t;

队列结构体整体示意图:

在这里插入图片描述

3. 队列相关 API 函数介绍

使用队列的主要流程:创建队列->写队列->读队列。

3.1 创建队列

创建队列相关API函数介绍:

函数描述
xQueueCreate()动态方式创建队列
xQueueCreateStatic()静态方式创建队列

动态和静态创建队列之间的区别:

  • 动态:队列所需的内存空间由 FreeRTOS 从 FreeRTOS 管理的堆中自动分配。
  • 静态:创建需要用户自行分配内存。

3.1.1 动态创建队列(常用)

#define	xQueueCreate(  uxQueueLength,   uxItemSize  )						xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), (queueQUEUE_TYPE_BASE ))

此函数用于使用动态方式创建队列,队列所需的内存空间由 FreeRTOS 从 FreeRTOS 管理的堆中自动分配 。

形参描述
uxQueueLength队列长度
uxItemSize队列项目的大小
返回值描述
NULL队列创建失败
其他值队列创建成功,返回队列句柄

前面说 FreeRTOS 基于队列实现了多种功能,每一种功能对应一种队列类型,队列类型的 queue.h 文件中有定义:

#define queueQUEUE_TYPE_BASE                  	( ( uint8_t ) 0U )	/* 队列 */
#define queueQUEUE_TYPE_SET                  	( ( uint8_t ) 0U )	/* 队列集 */
#define queueQUEUE_TYPE_MUTEX                 	( ( uint8_t ) 1U )	/* 互斥信号量 */
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE    	( ( uint8_t ) 2U )	/* 计数型信号量 */
#define queueQUEUE_TYPE_BINARY_SEMAPHORE     	( ( uint8_t ) 3U )	/* 二值信号量 */
#define queueQUEUE_TYPE_RECURSIVE_MUTEX       	( ( uint8_t ) 4U )	/* 递归互斥信号量 */ ```

3.2 写队列

往队列写入消息API函数:

函数(任务级+中断级)描述
xQueueSend()往队列的尾部写入消息
xQueueSendToBack()同 xQueueSend()
xQueueSendToFront()往队列的头部写入消息
xQueueOverwrite()覆写队列消息(只用于队列长度为 1 的情况)
xQueueSendFromISR()在中断中往队列的尾部写入消息
xQueueSendToBackFromISR()同 xQueueSendFromISR()
xQueueSendToFrontFromISR()在中断中往队列的头部写入消息
xQueueOverwriteFromISR()在中断中覆写队列消息(只用于队列长度为 1 的情况)

队列写入消息

#define	xQueueSend(  xQueue,   pvItemToQueue,   xTicksToWait  )xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define	xQueueSendToBack(  xQueue,   pvItemToQueue,   xTicksToWait  )xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
#define	xQueueSendToFront(  xQueue,   pvItemToQueue,   xTicksToWait  )xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
#define	xQueueOverwrite(  xQueue,   pvItemToQueue  )xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE )

可以看到这几个写入函数调用的是同一个函数 xQueueGenericSend(),只是指定了不同的写入位置!

覆写:队列长度为 1,只有一个队列项目,比如队列里有数据了,那覆写就是不管队列中有没有数据,都会再写进去覆盖,就是永远是写的进去的,所以是不会阻塞的,所以它的默认阻塞时间是 0,就直接跳过,直接继续写。
其他像尾部写入、头部写入,那这些它们都是会阻塞的,它们都是有一个阻塞时间的设置的,如果队列满了之后,它是写不进去的。那这个是覆写方式与其他方式它们之间的一个区别。

队列一共有 3 种写入位置 :

#define queueSEND_TO_BACK               ( ( BaseType_t ) 0 )		/* 写入队列尾部 */
#define queueSEND_TO_FRONT              ( ( BaseType_t ) 1 )		/* 写入队列头部 */
#define queueOVERWRITE                  ( ( BaseType_t ) 2 )		/* 覆写队列 */

注意:覆写方式写入队列,只有在队列的队列长度为 1 时,才能够使用

往队列写入消息函数入口参数解析:

BaseType_t	xQueueGenericSend(QueueHandle_t 	xQueue,const void * const 	pvItemToQueue,TickType_t 	xTicksToWait,const BaseType_t 	xCopyPosition); 
形参描述
xQueue待写入的队列
pvItemToQueue待写入消息
xTicksToWait阻塞超时时间
xCopyPosition写入的位置
返回值描述
pdTRUE队列写入成功
errQUEUE_FULL队列写入失败

3.3 读队列

从队列读取消息API函数:

函数(任务级+中断级)描述
xQueueReceive()从队列头部读取消息,并删除消息
xQueuePeek()从队列头部读取消息
xQueueReceiveFromISR()在中断中从队列头部读取消息,并删除消息
xQueuePeekFromISR()在中断中从队列头部读取消息
BaseType_t    xQueueReceive( QueueHandle_t   xQueue,  void *   const pvBuffer,  TickType_t   xTicksToWait )

此函数用于在任务中,从队列中读取消息,并且消息读取成功后,会将消息从队列中移除。

形参描述
xQueue待读取的队列
pvBuffer信息读取缓冲区
xTicksToWait阻塞超时时间
返回值描述
pdTRUE读取成功
pdFALSE读取失败
BaseType_t   xQueuePeek( QueueHandle_t   xQueue,   void * const   pvBuffer,   TickType_t   xTicksToWait )

此函数用于在任务中,从队列中读取消息, 但与函数 xQueueReceive()不同,此函数在成功读取消息后,并不会移除已读取的消息!

形参描述
xQueue待读取的队列
pvBuffer信息读取缓冲区
xTicksToWait阻塞超时时间
返回值描述
pdTRUE读取成功
pdFALSE读取失败

4. 队列操作实验

实验目的:学习 FreeRTOS 的队列相关API函数的使用 ,实现队列的入队和出队操作。
实验设计:将设计四个任务:start_task、task1、task2、task3

四个任务的功能如下:
start_task:用来创建task1和task2以及task3任务
task1:当按键 key0 或 key1 按下,将键值拷贝到队列 key_queue(入队);当按键 key_up 按下,将传输大数据,这里拷贝大数据的地址到队列 big_date_queue 中。
task2:读取队列 key_queue 中的消息(出队),打印出接收到的键值。
task3:从队列 big_date_queue 读取大数据地址,通过地址访问大数据。

4.1 创建队列

#include "queue.h"QueueHandle_t key_queue;        /* 小数据句柄 */
QueueHandle_t big_date_queue;   /* 大数据句柄 */
char buff[100] = {"我是一个大数组,大大的数组 124214 uhsidhaksjhdklsadhsaklj"};
/*** @brief       FreeRTOS例程入口函数* @param       无* @retval      无*/
void freertos_demo(void)
{    /* 队列的创建 */key_queue = xQueueCreate( 2, sizeof(uint8_t) );if(key_queue != NULL){printf("key_queue队列创建成功!!\r\n");}else printf("key_queue队列创建失败!!\r\n");big_date_queue = xQueueCreate( 1, sizeof(char *) );if(big_date_queue != NULL){printf("big_date_queue队列创建成功!!\r\n");}else printf("big_date_queue队列创建失败!!\r\n");xTaskCreate((TaskFunction_t         )   start_task,(char *                 )   "start_task",(configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,(void *                 )   NULL,(UBaseType_t            )   START_TASK_PRIO,(TaskHandle_t *         )   &start_task_handler );vTaskStartScheduler();
}

4.2 任务函数实现

/* 任务一,实现入队 */
void task1( void * pvParameters )
{uint8_t key = 0;char * buf;buf = buff; 														/* buf = &buff[0] */BaseType_t   err = 0;while(1) {key = key_scan(0);if(key == KEY0_PRES || key == KEY1_PRES){err = xQueueSend( key_queue, &key, portMAX_DELAY );			/* 写入队列、死等 */if(err != pdTRUE){printf("key_queue队列发送失败\r\n");}}else if(key == WKUP_PRES){err = xQueueSend( big_date_queue, &buf, portMAX_DELAY );	/* 写入队列、死等 */if(err != pdTRUE){printf("key_queue队列发送失败\r\n");}}vTaskDelay(10);}
}/* 任务二,小数据出队 */
void task2( void * pvParameters )
{uint8_t key = 0;BaseType_t err = 0;while(1){err = xQueueReceive(key_queue, &key, portMAX_DELAY);if(err != pdTRUE){printf("key_queue队列读取失败\r\n");}else {printf("key_queue读取队列成功,数据:%d\r\n",key);}}
}/* 任务三,大数据出队 */
void task3( void * pvParameters )
{char * buf;BaseType_t err = 0;while(1){err = xQueueReceive(big_date_queue, &buf, portMAX_DELAY);if(err != pdTRUE){printf("big_date_queue队列读取失败\r\n");}else {printf("数据:%s\r\n",buf);}}
}

5. 队列相关API函数解析

  • 队列的创建API函数:xQueueCreate( )
  • 往队列写入数据API函数(入队):xQueueSend( )
  • 从队列读取数据API函数(出队): xQueueReceive( )

更多的队列相关API函数讲解可以查看《FreeRTOS开发指南》第十三章—队列

http://www.15wanjia.com/news/46419.html

相关文章:

  • 甘肃网站建设公司软文营销的特点
  • wordpress 简体中文网站关键词优化方法
  • 遂宁市住房与城乡建设厅网站云南网站建设公司哪家好
  • 潍坊高端网站建设公司域名注册查询入口
  • 崇文网站建设海外网站seo优化
  • 开发外贸产品的网站域名查询ip地址
  • 网站备案名称必须是公司名成全高清免费观看mv
  • 微博上如何做网站推广seo工具在线访问
  • 在线免费做网站株洲网站设计外包首选
  • 网站建设付款方式百度快照推广有效果吗
  • 昆明网站制作公司帮人推广的平台
  • 网站策划怎么做内容网络推广费用
  • 简述企业网站的网络营销功能爱站网站长工具
  • 做网站毕业答辩问题网站优化有哪些类型
  • 全国疫情最新新增关键词优化举例
  • 制作动态网站的步骤广州网站建设推广专家
  • 手机网站开发 图库类如何写软文推广产品
  • 国外十大黄冈推广郑州seo技术服务
  • 如何建设国外的网站广告策划公司
  • 网站建设时间规划表搜索引擎网站优化推广
  • 成都最有名的设计公司网站优化方案
  • 供应优惠的网站网页归档seo提供服务
  • 广州安全教育平台网seo怎么优化方法
  • 绵阳市 政府网站建设上海搜索引擎优化公司
  • 福州网站怎么做的seo优化排名方法
  • 做网站月薪资多少钱企业推广网站有哪些
  • 邯郸做网站的石家庄网站建设就找
  • 移动端网站建设的请示网站建设哪个公司好
  • 苏州seo网站系统赛事资讯赛马资料
  • b2c电子商务模式指的是seo关键词排名优化是什么