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

男女直接做网站windows优化大师和360哪个好

男女直接做网站,windows优化大师和360哪个好,自媒体是干什么的,自适应网站建站基本概念 队列又称消息队列#xff0c;是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息#xff0c;并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息#xff0c;当队列中的消息为空时#xff0c;挂起读取任务…基本概念 队列又称消息队列是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息并根据不同的接口确定传递的消息是否存放在队列空间中。 任务能够从队列里面读取消息当队列中的消息为空时挂起读取任务当队列中有新消息时挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息当队列已经写满消息时挂起写入任务当队列中有空闲消息节点时挂起的写入任务被唤醒并写入消息。如果将读队列和写队列的超时时间设置为0则不会挂起任务接口会直接返回这就是非阻塞模式。 消息队列提供了异步处理机制允许将一个消息放入队列但不立即处理。同时队列还有缓冲消息的作用。 队列用于任务间通信可以实现消息的异步处理。同时消息的发送方和接收方不需要彼此联系两者间是解耦的。 队列特性 消息以先进先出的方式排队支持异步读写。读队列和写队列都支持超时机制。每读取一条消息就会将该消息节点设置为空闲。发送消息类型由通信双方约定可以允许不同长度不超过队列的消息节点大小的消息。一个任务能够从任意一个消息队列接收和发送消息。多个任务能够从同一个消息队列接收和发送消息。创建队列时所需的队列空间默认支持接口内系统自行动态申请内存的方式同时也支持将用户分配的队列空间作为接口入参传入的方式。 消息队列长什么样? #ifndef LOSCFG_BASE_IPC_QUEUE_LIMIT #define LOSCFG_BASE_IPC_QUEUE_LIMIT 1024 //队列个数 #endif LITE_OS_SEC_BSS LosQueueCB *g_allQueue NULL;//消息队列池 LITE_OS_SEC_BSS STATIC LOS_DL_LIST g_freeQueueList;//空闲队列链表管分配的需要队列从这里申请typedef struct {UINT8 *queueHandle; /** Pointer to a queue handle */ //指向队列句柄的指针UINT16 queueState; /** Queue state */ //队列状态UINT16 queueLen; /** Queue length */ //队列中消息总数的上限值由创建时确定不再改变UINT16 queueSize; /** Node size */ //消息节点大小由创建时确定不再改变即定义了每个消息长度的上限.UINT32 queueID; /** queueID */ //队列IDUINT16 queueHead; /** Node head */ //消息头节点位置数组下标UINT16 queueTail; /** Node tail */ //消息尾节点位置数组下标UINT16 readWriteableCnt[OS_QUEUE_N_RW]; /** Count of readable or writable resources 0:readable 1:writable *///队列中可写或可读消息数0表示可读1表示可写LOS_DL_LIST readWriteList[OS_QUEUE_N_RW]; /** the linked list to be read or written 0:readlist 1:writelist *///挂的都是等待读/写消息的任务链表0表示读消息的链表1表示写消息的任务链表LOS_DL_LIST memList; /** Pointer to the memory linked list */ //note_why 这里尚未搞明白是啥意思 是共享内存吗 } LosQueueCB;//读写队列分离 解读 和进程线程定时器一样消息队列也由全局统一的消息队列池管理池有多大?默认是1024鸿蒙内核对消息的总个数有限制queueLen消息总数的上限在创建队列的时候需指定不能更改.对每个消息的长度也有限制 queueSize 规定了消息的大小也是在创建的时候指定.为啥要指定总个数和每个的总大小是因为内核一次性会把队列的总内存(queueLen*queueSize)申请下来确保不会出现后续使用过程中内存不够的问题出现但同时也带来了内存的浪费因为很可能大部分时间队列并没有跑满.队列的读取由queueHeadqueueTail管理Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置也是空闲消息节点的起始位置。队列刚创建时Head和Tail均指向队列起始位置写队列时根据readWriteableCnt[1]判断队列是否可以写入不能对已满readWriteableCnt[1]为0队列进行写操作。写队列支持两种写入方式向队列尾节点写入也可以向队列头节点写入。尾节点写入时根据Tail找到起始空闲消息节点作为数据写入对象如果Tail已经指向队列尾部则采用回卷方式。头节点写入时将Head的前一个节点作为数据写入对象如果Head指向队列起始位置则采用回卷方式。读队列时根据readWriteableCnt[0]判断队列是否有消息需要读取对全部空闲readWriteableCnt[0]为0队列进行读操作会引起任务挂起。如果队列可以读取消息则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。删除队列时根据队列ID找到对应队列把队列状态置为未使用把队列控制块置为初始状态。如果是通过系统动态申请内存方式创建的队列还会释放队列所占内存。留意readWriteList这又是两个双向链表 双向链表是内核最重要的结构体牢牢的寄生在宿主结构体上.readWriteList上挂的是未来读/写消息队列的任务列表. 初始化队列 LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID)//消息队列模块初始化 {LosQueueCB *queueNode NULL;UINT32 index;UINT32 size;size LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB);//支持1024个IPC队列/* system resident memory dont free */g_allQueue (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0 size);//常驻内存if (g_allQueue NULL) {return LOS_ERRNO_QUEUE_NO_MEMORY;}(VOID)memset_s(g_allQueue size 0 size);//清0LOS_ListInit(g_freeQueueList);//初始化空闲链表for (index 0; index LOSCFG_BASE_IPC_QUEUE_LIMIT; index) {//循环初始化每个消息队列queueNode ((LosQueueCB *)g_allQueue) index;//一个一个来queueNode-queueID index;//这可是 队列的身份证LOS_ListTailInsert(g_freeQueueList queueNode-readWriteList[OS_QUEUE_WRITE]);//通过写节点挂到空闲队列链表上}//这里要注意是用 readWriteList 挂到 g_freeQueueList链上的所以要通过 GET_QUEUE_LIST 来找到 LosQueueCBif (OsQueueDbgInitHook() ! LOS_OK) {//调试队列使用的.return LOS_ERRNO_QUEUE_NO_MEMORY;}return LOS_OK; } 解读 初始队列模块对几个全局变量赋值创建消息队列池所有池都是常驻内存关于池后续有专门的文章整理到目前为止已经解除到了进程池任务池定时器池队列池将LOSCFG_BASE_IPC_QUEUE_LIMIT个队列挂到空闲链表g_freeQueueList上供后续分配和回收.熟悉内核全局资源管理的对这种方式应该不会再陌生. 创建队列 //创建一个队列根据用户传入队列长度和消息节点大小来开辟相应的内存空间以供该队列使用参数queueID带走队列ID LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *queueName UINT16 len UINT32 *queueIDUINT32 flags UINT16 maxMsgSize) {LosQueueCB *queueCB NULL;UINT32 intSave;LOS_DL_LIST *unusedQueue NULL;UINT8 *queue NULL;UINT16 msgSize;(VOID)queueName;(VOID)flags;if (queueID NULL) {return LOS_ERRNO_QUEUE_CREAT_PTR_NULL;}if (maxMsgSize (OS_NULL_SHORT - sizeof(UINT32))) {// maxMsgSize上限 为啥要减去 sizeof(UINT32) 因为前面存的是队列的大小return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;}if ((len 0) || (maxMsgSize 0)) {return LOS_ERRNO_QUEUE_PARA_ISZERO;}msgSize maxMsgSize sizeof(UINT32);//总size 消息体内容长度 消息大小(UINT32) /** Memory allocation is time-consuming to shorten the time of disable interrupt* move the memory allocation to here.*///内存分配非常耗时为了缩短禁用中断的时间将内存分配移到此处用的时候分配队列内存queue (UINT8 *)LOS_MemAlloc(m_aucSysMem1 (UINT32)len * msgSize);//从系统内存池中分配由这里提供读写队列的内存if (queue NULL) {//这里是一次把队列要用到的所有最大内存都申请下来了能保证不会出现后续使用过程中内存不够的问题出现return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;//调用处有 OsSwtmrInit sys_mbox_new DoMqueueCreate }SCHEDULER_LOCK(intSave);if (LOS_ListEmpty(g_freeQueueList)) {//没有空余的队列ID的处理注意软时钟定时器是由 g_swtmrCBArray统一管理的里面有正在使用和可分配空闲的队列SCHEDULER_UNLOCK(intSave);//g_freeQueueList是管理可用于分配的队列链表申请消息队列的ID需要向它要OsQueueCheckHook();(VOID)LOS_MemFree(m_aucSysMem1 queue);//没有就要释放 queue申请的内存return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;}unusedQueue LOS_DL_LIST_FIRST(g_freeQueueList);//找到一个没有被使用的队列LOS_ListDelete(unusedQueue);//将自己从g_freeQueueList中摘除 unusedQueue只是个 LOS_DL_LIST 结点.queueCB GET_QUEUE_LIST(unusedQueue);//通过unusedQueue找到整个消息队列(LosQueueCB)queueCB-queueLen len; //队列中消息的总个数注意这个一旦创建是不能变的.queueCB-queueSize msgSize;//消息节点的大小注意这个一旦创建也是不能变的.queueCB-queueHandle queue; //队列句柄队列内容存储区. queueCB-queueState OS_QUEUE_INUSED; //队列状态使用中queueCB-readWriteableCnt[OS_QUEUE_READ] 0;//可读资源计数OS_QUEUE_READ(0):可读.queueCB-readWriteableCnt[OS_QUEUE_WRITE] len;//可些资源计数 OS_QUEUE_WRITE(1):可写 默认len可写.queueCB-queueHead 0;//队列头节点queueCB-queueTail 0;//队列尾节点LOS_ListInit(queueCB-readWriteList[OS_QUEUE_READ]);//初始化可读队列链表LOS_ListInit(queueCB-readWriteList[OS_QUEUE_WRITE]);//初始化可写队列链表LOS_ListInit(queueCB-memList);//OsQueueDbgUpdateHook(queueCB-queueID OsCurrTaskGet()-taskEntry);//在创建或删除队列调试信息时更新任务条目SCHEDULER_UNLOCK(intSave);*queueID queueCB-queueID;//带走队列IDreturn LOS_OK; } 解读 创建和初始化一个LosQueueCB动态分配内存来保存消息内容LOS_MemAlloc(m_aucSysMem1 (UINT32)len * msgSize);msgSize maxMsgSize sizeof(UINT32);头四个字节放消息的长度但消息最大长度不能超过maxMsgSizereadWriteableCnt记录读/写队列的数量独立计算readWriteList挂的是等待读取队列的任务链表 将在OsTaskWait(queueCB-readWriteList[readWrite] timeout TRUE);中将任务挂到链表上. 关键函数OsQueueOperate 队列的读写都要经过 OsQueueOperate /************************************************ 队列操作.是读是写由operateType定 本函数是消息队列最重要的一个函数可以分析出读取消息过程中 发生的细节涉及任务的唤醒和阻塞阻塞链表任务的相互提醒. ************************************************/ UINT32 OsQueueOperate(UINT32 queueID UINT32 operateType VOID *bufferAddr UINT32 *bufferSize UINT32 timeout) {LosQueueCB *queueCB NULL;LosTaskCB *resumedTask NULL;UINT32 ret;UINT32 readWrite OS_QUEUE_READ_WRITE_GET(operateType);//获取读/写操作标识UINT32 intSave;SCHEDULER_LOCK(intSave);queueCB (LosQueueCB *)GET_QUEUE_HANDLE(queueID);//获取对应的队列控制块ret OsQueueOperateParamCheck(queueCB queueID operateType bufferSize);//参数检查if (ret ! LOS_OK) {goto QUEUE_END;}if (queueCB-readWriteableCnt[readWrite] 0) {//根据readWriteableCnt判断队列是否有消息读/写if (timeout LOS_NO_WAIT) {//不等待直接退出ret OS_QUEUE_IS_READ(operateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;goto QUEUE_END;}if (!OsPreemptableInSched()) {//不支持抢占式调度ret LOS_ERRNO_QUEUE_PEND_IN_LOCK;goto QUEUE_END;}//任务等待这里很重要啊将自己从就绪列表摘除让出了CPU并发起了调度并挂在readWriteList[readWrite]上挂的都等待读/写消息的taskret OsTaskWait(queueCB-readWriteList[readWrite] timeout TRUE);//任务被唤醒后会回到这里执行什么时候会被唤醒?当然是有消息的时候!if (ret LOS_ERRNO_TSK_TIMEOUT) {//唤醒后如果超时了返回读/写消息失败ret LOS_ERRNO_QUEUE_TIMEOUT;goto QUEUE_END;//}} else {queueCB-readWriteableCnt[readWrite]--;//对应队列中计数器--说明一条消息只能被读/写一次}OsQueueBufferOperate(queueCB operateType bufferAddr bufferSize);//发起读或写队列操作if (!LOS_ListEmpty(queueCB-readWriteList[!readWrite])) {//如果还有任务在排着队等待读/写入消息(当时不能读/写的原因有可能当时队列满了)resumedTask OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(queueCB-readWriteList[!readWrite]));//取出要读/写消息的任务OsTaskWake(resumedTask);//唤醒任务去读/写消息啊SCHEDULER_UNLOCK(intSave);LOS_MpSchedule(OS_MP_CPU_ALL);//让所有CPU发出调度申请因为很可能那个要读/写消息的队列是由其他CPU执行LOS_Schedule();//申请调度return LOS_OK;} else {queueCB-readWriteableCnt[!readWrite];//对应队列读/写中计数器}QUEUE_END:SCHEDULER_UNLOCK(intSave);return ret; } 解读 queueID 指定操作消息队列池中哪个消息队列operateType 表示本次是是读/写消息bufferAddrbufferSize表示如果读操作用buf接走数据如果写操作将buf写入队列.timeout只用于当队列中没有读/写内容时的等待. 当读消息时发现队列中没有可读的消息此时timeout决定是否将任务挂入等待读队列任务链表当写消息时发现队列中没有空间用于写的消息此时timeout决定是否将任务挂入等待写队列任务链表 if (!LOS_ListEmpty(queueCB-readWriteList[!readWrite]))最有意思的是这行代码. 在一次读消息完成后会立即唤醒写队列任务链表的任务因为读完了就有了剩余空间等待写队列的任务往往是因为没有空间而进入等待状态.在一次写消息完成后会立即唤醒读队列任务链表的任务因为写完了队列就有了新消息等待读队列的任务往往是因为队列中没有消息而进入等待状态. 编程实例 创建一个队列两个任务。任务1调用写队列接口发送消息任务2通过读队列接口接收消息。 通过LOS_TaskCreate创建任务1和任务2。通过LOS_QueueCreate创建一个消息队列。在任务1 send_Entry中发送消息。在任务2 recv_Entry中接收消息。通过LOS_QueueDelete删除队列。 #include los_task.h #include los_queue.hstatic UINT32 g_queue; #define BUFFER_LEN 50VOID send_Entry(VOID) {UINT32 i 0;UINT32 ret 0;CHAR abuf[] test is message x;UINT32 len sizeof(abuf);while (i 5) {abuf[len -2] 0 i;i;ret LOS_QueueWriteCopy(g_queue abuf len 0);if(ret ! LOS_OK) {dprintf(send message failure error: %x\n ret);}LOS_TaskDelay(5);} }VOID recv_Entry(VOID) {UINT32 ret 0;CHAR readBuf[BUFFER_LEN] {0};UINT32 readLen BUFFER_LEN;while (1) {ret LOS_QueueReadCopy(g_queue readBuf readLen 0);if(ret ! LOS_OK) {dprintf(recv message failure error: %x\n ret);break;}dprintf(recv message: %s\n readBuf);LOS_TaskDelay(5);}while (LOS_OK ! LOS_QueueDelete(g_queue)) {LOS_TaskDelay(1);}dprintf(delete the queue success!\n); }UINT32 Example_CreateTask(VOID) {UINT32 ret 0; UINT32 task1 task2;TSK_INIT_PARAM_S initParam;initParam.pfnTaskEntry (TSK_ENTRY_FUNC)send_Entry;initParam.usTaskPrio 9;initParam.uwStackSize LOS_TASK_MIN_STACK_SIZE;initParam.pcName sendQueue; #ifdef LOSCFG_KERNEL_SMPinitParam.usCpuAffiMask CPUID_TO_AFFI_MASK(ArchCurrCpuid()); #endifinitParam.uwResved LOS_TASK_STATUS_DETACHED;LOS_TaskLock();ret LOS_TaskCreate(task1 initParam);if(ret ! LOS_OK) {dprintf(create task1 failed error: %x\n ret);return ret;}initParam.pcName recvQueue;initParam.pfnTaskEntry (TSK_ENTRY_FUNC)recv_Entry;ret LOS_TaskCreate(task2 initParam);if(ret ! LOS_OK) {dprintf(create task2 failed error: %x\n ret);return ret;}ret LOS_QueueCreate(queue 5 g_queue 0 BUFFER_LEN);if(ret ! LOS_OK) {dprintf(create queue failure error: %x\n ret);}dprintf(create the queue success!\n);LOS_TaskUnlock();return ret; } 结果验证 create the queue success! recv message: test is message 0 recv message: test is message 1 recv message: test is message 2 recv message: test is message 3 recv message: test is message 4 recv message failure error: 200061d delete the queue success! 总结 消息队列解决任务间大数据的传递以一种异步解耦的方式实现任务通讯全局由消息队列池统一管理在创建消息队列时申请内存块存储消息内存.读/写操作统一管理分开执行A任务 读/写完消息后会立即唤醒等待写/读的B任务. 鸿蒙全栈开发全新学习指南 也为了积极培养鸿蒙生态人才让大家都能学习到鸿蒙开发最新的技术针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群整理了一套纯血版鸿蒙HarmonyOS Next全栈开发技术的学习路线【包含了大APP实战项目开发】。 本路线共分为四个阶段 第一阶段鸿蒙初中级开发必备技能 第二阶段鸿蒙南北双向高工技能基础gitee.com/MNxiaona/733GH 第三阶段应用开发中高级就业技术 第四阶段全网首发-工业级南向设备开发就业技术https://gitee.com/MNxiaona/733GH 《鸿蒙 (Harmony OS)开发学习手册》共计892页 如何快速入门 1.基本概念 2.构建第一个ArkTS应用 3.…… 开发基础知识:gitee.com/MNxiaona/733GH 1.应用基础知识 2.配置文件 3.应用数据管理 4.应用安全管理 5.应用隐私保护 6.三方应用调用管控机制 7.资源分类与访问 8.学习ArkTS语言 9.…… 基于ArkTS 开发 1.Ability开发 2.UI开发 3.公共事件与通知 4.窗口管理 5.媒体 6.安全 7.网络与链接 8.电话服务 9.数据管理 10.后台任务(Background Task)管理 11.设备管理 12.设备使用信息统计 13.DFX 14.国际化开发 15.折叠屏系列 16.…… 鸿蒙开发面试真题含参考答案:gitee.com/MNxiaona/733GH 鸿蒙入门教学视频 美团APP实战开发教学gitee.com/MNxiaona/733GH 写在最后 如果你觉得这篇内容对你还蛮有帮助我想邀请你帮我三个小忙点赞转发有你们的 『点赞和评论』才是我创造的动力。关注小编同时可以期待后续文章ing不定期分享原创知识。想要获取更多完整鸿蒙最新学习资源请移步前往小编gitee.com/MNxiaona/733GH
http://www.tj-hxxt.cn/news/131812.html

相关文章:

  • 做网站跟app沌口开发区网页设计
  • 网站丢失了怎么找回来建设视频网站要求
  • asp网站模板源码wordpress导航去掉多余的样式
  • 典当行网站策划网站建设 精品课程
  • 百度网站的设计风格网站如何进行代码优化
  • 菏泽网站建设公司蓝希科技客户管理软件排名免费
  • 安卓软件开发公司宁波seo网络推广报价
  • 网站域名费会计分录怎么做贵港网站设计
  • 中煤第三建设集团网站外贸建站代理
  • 网站的商桥怎么做wordpress定时器插件
  • 网站建设通查询wordpress 外链跳转
  • 自已建网站微信登录重庆门户网站开发报价
  • 网络公司代做的网站注意事项洛阳便宜网站建设价格
  • 网站收录率高端汽车网站建设
  • 成品网站和模板建站上海企业建站方案
  • 南宁做网站seo中建西部建设网站
  • 有哪些公司百度seo2022
  • 邢台企业网站建设报价网络企业网站建设方案
  • 青岛建站平台广州市住建局官网
  • 怎么在企业站建立网站吗人社通成都app下载
  • 企业网站开发注册专做皮鞋销售网站
  • asp网站例子搭建免费个人网站2022
  • 网站栏目设计规划表网站设计宣传广告方案
  • 手机下载视频网站模板下载失败网站建设周期计划
  • 手机网站竞价单页wordpress获取单篇文章
  • 肃宁县网站建设价格6做网站
  • 集团网站开发公司手机如何制作网站
  • 郑州网站建设公司qq百度怎么发免费广告
  • 静态网站做淘宝客商丘企业网站建设服务
  • cms网站后台管理系统专业的网页制作服务好