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

比较好的能组数学卷的网站做教案的wordpress 免费主题

比较好的能组数学卷的网站做教案的,wordpress 免费主题,中铁招标在哪个平台,如何设置一个网站往期知识点记录#xff1a; 鸿蒙#xff08;HarmonyOS#xff09;应用层开发#xff08;北向#xff09;知识点汇总 轻内核M核源码分析系列一 数据结构-双向循环链表 轻内核M核源码分析系列二 数据结构-任务就绪队列 鸿蒙轻内核M核源码分析系列三 数据结构-任务排序链表 轻…往期知识点记录 鸿蒙HarmonyOS应用层开发北向知识点汇总 轻内核M核源码分析系列一 数据结构-双向循环链表 轻内核M核源码分析系列二 数据结构-任务就绪队列 鸿蒙轻内核M核源码分析系列三 数据结构-任务排序链表 轻内核M核源码分析系列四 中断Hwi 轻内核M核源码分析系列五 时间管理 轻内核M核源码分析系列六 任务及任务调度1任务栈 轻内核M核源码分析系列六 任务及任务调度2任务模块 轻内核M核源码分析系列六 任务及任务调度3任务调度模块 轻内核M核源码分析系列七 动态内存Dynamic Memory 轻内核M核源码分析系列八 静态内存MemoryBox 轻内核M核源码分析系列九 互斥锁Mutex 轻内核M核源码分析系列十 软件定时器Swtmr 轻内核M核源码分析系列十一 (1)信号量Semaphore 轻内核M核源码分析系列十一 (2)信号量Semaphore 轻内核M核源码分析系列十二 事件Event 轻内核M核源码分析系列十三 消息队列Queue 轻内核M核源码分析系列十四 软件定时器Swtmr 轻内核M核源码分析系列十五 CPU使用率CPUP 轻内核M核源码分析系列十六 MPU内存保护单元 轻内核M核源码分析系列十七1 异常钩子函数类型介绍 轻内核M核源码分析系列十七2 异常钩子函数的注册操作 轻内核M核源码分析系列十七3 异常信息ExcInfo 轻内核M核源码分析系列十八 Fault异常处理 轻内核M核源码分析系列十九 Musl LibC 轻内核M核源码分析系列二十 Newlib C 持续更新中…… 队列Queue是一种常用于任务间通信的数据结构。任务能够从队列里面读取消息当队列中的消息为空时挂起读取任务当队列中有新消息时挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息当队列已经写满消息时挂起写入任务当队列中有空闲消息节点时挂起的写入任务被唤醒并写入消息。如果将读队列和写队列的超时时间设置为0则不会挂起任务接口会直接返回这就是非阻塞模式。消息队列提供了异步处理机制允许将一个消息放入队列但不立即处理。同时队列还有缓冲消息的作用。 本文通过分析鸿蒙轻内核队列模块的源码掌握队列使用上的差异。本文中所涉及的源码以OpenHarmony LiteOS-M内核为例均可以在开源站点https://gitee.com/openharmony/kernel_liteos_m 获取。 接下来我们看下队列的结构体队列初始化队列常用操作的源代码。 1、队列结构体定义和常用宏定义 1.1 队列结构体定义 在文件kernel\include\los_queue.h中定义队列控制块结构体为LosQueueCB结构体源代码如下。队列状态.queueState取值OS_QUEUE_UNUSED、OS_QUEUE_INUSED其他结构体成员见注释部分。 typedef struct {UINT8 *queue; /** 队列内存空间的指针 */UINT16 queueState; /** 队列的使用状态 */UINT16 queueLen; /** 队列长度即消息数量 */UINT16 queueSize; /** 消息节点大小 */UINT16 queueID; /** 队列编号 */UINT16 queueHead; /** 消息头节点位置 */UINT16 queueTail; /** 消息尾节点位置 */UINT16 readWriteableCnt[OS_READWRITE_LEN]; /** 2维数组可读、可写的消息数量, 0:可读, 1:可写 */LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /** 2维双向链表数组阻塞读、写任务的双向链表, 0:读链表, 1:写链表 */LOS_DL_LIST memList; /** 内存节点双向链表 */ } LosQueueCB;1.2 队列常用宏定义 系统支持创建多少队列是根据开发板情况使用宏LOSCFG_BASE_IPC_QUEUE_LIMIT定义的每一个队列queueID是queueID类型的取值为[0,LOSCFG_BASE_IPC_QUEUE_LIMIT)表示队列池中各个队列的编号。 ⑴处的宏从队列池中获取指定队列编号QueueID对应的队列控制块。⑵处根据双向链表节点readWriteList[OS_QUEUE_WRITE]获取队列控制块内存地址。 ⑴ #define GET_QUEUE_HANDLE(QueueID) (((LosQueueCB *)g_allQueue) (QueueID))⑵ #define GET_QUEUE_LIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosQueueCB, readWriteList[OS_QUEUE_WRITE])另外队列中还提供了比较重要的队列读取消息操作相关的枚举和宏。枚举QueueReadWrite区分队列的读和写枚举QueueHeadTail区分队列的首和尾枚举QueuePointOrNot区分读写消息时是使用值还是指针。 队列的操作类型使用3比特位的数字来表示见宏OS_QUEUE_OPERATE_TYPE的定义其中高1位表示读写数值还是读写指针地址中1位表示队首还是队尾低1位表示读取还是写入。枚举和宏的定义如下 typedef enum {OS_QUEUE_READ,OS_QUEUE_WRITE } QueueReadWrite;typedef enum {OS_QUEUE_HEAD,OS_QUEUE_TAIL } QueueHeadTail;typedef enum {OS_QUEUE_NOT_POINT,OS_QUEUE_POINT } QueuePointOrNot;#define OS_QUEUE_OPERATE_TYPE(ReadOrWrite, HeadOrTail, PointOrNot) \(((UINT32)(PointOrNot) 2) | ((UINT32)(HeadOrTail) 1) | (ReadOrWrite)) #define OS_QUEUE_READ_WRITE_GET(type) ((type) (0x01)) #define OS_QUEUE_READ_HEAD (OS_QUEUE_READ | (OS_QUEUE_HEAD 1)) #define OS_QUEUE_READ_TAIL (OS_QUEUE_READ | (OS_QUEUE_TAIL 1)) #define OS_QUEUE_WRITE_HEAD (OS_QUEUE_WRITE | (OS_QUEUE_HEAD 1)) #define OS_QUEUE_WRITE_TAIL (OS_QUEUE_WRITE | (OS_QUEUE_TAIL 1)) #define OS_QUEUE_OPERATE_GET(type) ((type) (0x03)) #define OS_QUEUE_IS_POINT(type) ((type) (0x04)) #define OS_QUEUE_IS_READ(type) (OS_QUEUE_READ_WRITE_GET(type) OS_QUEUE_READ) #define OS_QUEUE_IS_WRITE(type) (OS_QUEUE_READ_WRITE_GET(type) OS_QUEUE_WRITE) #define OS_READWRITE_LEN 22、队列初始化 队列在内核中默认开启用户可以通过宏LOSCFG_BASE_IPC_QUEUE进行关闭。开启队列的情况下在系统启动时在kernel\src\los_init.c中调用OsQueueInit()进行队列模块初始化。下面我们分析下队列初始化的代码。 ⑴为队列申请内存如果申请失败则返回错误。⑵初始化双向循环链表g_freeQueueList维护未使用的队列。⑶循环每一个队列进行初始化为每一个队列节点指定索引queueID并把队列节点插入未使用队列双向链表g_freeQueueList。代码上可以看出挂在未使用队列双向链表上的节点是每个队列控制块的写阻塞任务链表节点.readWriteList[OS_QUEUE_WRITE]。 LITE_OS_SEC_TEXT_INIT UINT32 OsQueueInit(VOID) {LosQueueCB *queueNode NULL;UINT16 index;if (LOSCFG_BASE_IPC_QUEUE_LIMIT 0) {return LOS_ERRNO_QUEUE_MAXNUM_ZERO;}⑴ g_allQueue (LosQueueCB *)LOS_MemAlloc(m_aucSysMem0, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB));if (g_allQueue NULL) {return LOS_ERRNO_QUEUE_NO_MEMORY;}(VOID)memset_s(g_allQueue, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB),0, LOSCFG_BASE_IPC_QUEUE_LIMIT * sizeof(LosQueueCB));⑵ LOS_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]);}return LOS_OK; }3、队列常用操作 3.1 队列创建 创建队列函数是LOS_QueueCreate()先看看该函数的参数queueName是队列名称实际上并没有使用。len是队列中消息的数量queueID是队列编号flags保留未使用。maxMsgSize是队列中每条消息的最大大小。 我们分析下创建队列的代码。⑴处对参数进行校验队列编码不能为空队列消息长度不能太大队列消息数量和队列消息大小不能为0。⑵处计算消息的实际最大大小msgSize即maxMsgSize sizeof(UINT32)消息最大大小再加4个字节在消息的最后4个字节用来保存消息的实际长度。然后调用⑶处函数LOS_MemAlloc()为对队列动态申请内存如果内存申请失败则返回错误码。 ⑷处判断g_freeQueueList是否为空如果没有可以使用的队列释放前文申请的内存。⑸处如果g_freeQueueList不为空则获取第一个可用的队列节点接着从双向链表g_freeQueueList中删除然后调用宏GET_QUEUE_LIST获取LosQueueCB *queueCB初始化创建的队列信息包含队列的长度.queueLen、消息大小.queueSize队列内存空间.queue消息状态.queueState可读的数量.readWriteableCnt[OS_QUEUE_READ]为0可写的数量readWriteableCnt[OS_QUEUE_WRITE]为队列消息长度len队列头位置.queueHead和尾位置.queueTail为0。 ⑹初始化双向链表.readWriteList[OS_QUEUE_READ]阻塞在这个队列上的读消息任务会挂在这个链表上。初始化双向链表.readWriteList[OS_QUEUE_WRITE]阻塞在这个队列上的写消息任务会挂在这个链表上。初始化双向链表.memList。⑺赋值给输出参数*queueID后续程序使用这个队列编号对队列进行其他操作。 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *queueName,UINT16 len,UINT32 *queueID,UINT32 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))) {return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;}if ((len 0) || (maxMsgSize 0)) {return LOS_ERRNO_QUEUE_PARA_ISZERO;} ⑵ msgSize maxMsgSize sizeof(UINT32);/* Memory allocation is time-consuming, to shorten the time of disable interrupt,move the memory allocation to here. */ ⑶ queue (UINT8 *)LOS_MemAlloc(m_aucSysMem0, len * msgSize);if (queue NULL) {return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;}intSave LOS_IntLock(); ⑷ if (LOS_ListEmpty(g_freeQueueList)) {LOS_IntRestore(intSave);(VOID)LOS_MemFree(m_aucSysMem0, queue);return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;}⑸ unusedQueue LOS_DL_LIST_FIRST((g_freeQueueList));LOS_ListDelete(unusedQueue);queueCB (GET_QUEUE_LIST(unusedQueue));queueCB-queueLen len;queueCB-queueSize msgSize;queueCB-queue queue;queueCB-queueState OS_QUEUE_INUSED;queueCB-readWriteableCnt[OS_QUEUE_READ] 0;queueCB-readWriteableCnt[OS_QUEUE_WRITE] 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);LOS_IntRestore(intSave);⑺ *queueID queueCB-queueID;OsHookCall(LOS_HOOK_TYPE_QUEUE_CREATE, queueCB);return LOS_OK; }3.2 队列删除 我们可以使用函数LOS_QueueDelete(UINT32 queueID)来删除队列下面通过分析源码看看如何删除队列的。 ⑴处判断队列queueID是否超过LOSCFG_BASE_IPC_QUEUE_LIMIT如果超过则返回错误码。如果队列编号没有问题获取队列控制块LosQueueCB *queueCB。⑵处判断要删除的队列处于未使用状态则跳转到错误标签QUEUE_END进行处理。⑶如果队列的阻塞读、阻塞写任务列表不为空或内存节点链表不为空则不允许删除跳转到错误标签进行处理。⑷处检验队列的可读、可写数量是否出错。 ⑸处使用指针UINT8 *queue保存队列的内存空间⑹处把.queue置空把.queueState设置为未使用OS_QUEUE_UNUSED并把队列节点插入未使用队列双向链表g_freeQueueList。接下来会需要调用⑺处函数LOS_MemFree()释放队列内存空间。 LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 queueID) {LosQueueCB *queueCB NULL;UINT8 *queue NULL;UINT32 intSave;UINT32 ret;⑴ if (queueID LOSCFG_BASE_IPC_QUEUE_LIMIT) {return LOS_ERRNO_QUEUE_NOT_FOUND;}intSave LOS_IntLock();queueCB (LosQueueCB *)GET_QUEUE_HANDLE(queueID); ⑵ if (queueCB-queueState OS_QUEUE_UNUSED) {ret LOS_ERRNO_QUEUE_NOT_CREATE;goto QUEUE_END;}⑶ if (!LOS_ListEmpty(queueCB-readWriteList[OS_QUEUE_READ])) {ret LOS_ERRNO_QUEUE_IN_TSKUSE;goto QUEUE_END;}if (!LOS_ListEmpty(queueCB-readWriteList[OS_QUEUE_WRITE])) {ret LOS_ERRNO_QUEUE_IN_TSKUSE;goto QUEUE_END;}if (!LOS_ListEmpty(queueCB-memList)) {ret LOS_ERRNO_QUEUE_IN_TSKUSE;goto QUEUE_END;}⑷ if ((queueCB-readWriteableCnt[OS_QUEUE_WRITE] queueCB-readWriteableCnt[OS_QUEUE_READ]) !queueCB-queueLen) {ret LOS_ERRNO_QUEUE_IN_TSKWRITE;goto QUEUE_END;}⑸ queue queueCB-queue; ⑹ queueCB-queue (UINT8 *)NULL;queueCB-queueState OS_QUEUE_UNUSED;LOS_ListAdd(g_freeQueueList, queueCB-readWriteList[OS_QUEUE_WRITE]);LOS_IntRestore(intSave);OsHookCall(LOS_HOOK_TYPE_QUEUE_DELETE, queueCB);⑺ ret LOS_MemFree(m_aucSysMem0, (VOID *)queue);return ret;QUEUE_END:LOS_IntRestore(intSave);return ret; }下面就来看看队列的读写有2点需要注意 队首、队尾的读写 只支持队首读取不能队尾读取否则就不算队列了。除了正常的队尾写消息外还提供插队机制支持从队首写入。 队列消息数据内容 往队列中写入的消息的类型有2种即支持按地址写入和按值写入带拷贝。按哪种类型写入就需要配对的按相应的类型去读取。 队列读取接口的类别归纳如下 读写接口类别接口名称描述读队列/队尾写队列LOS_QueueRead、 LOS_QueueWrite从指定队列头节点读、往队列尾节点写入。队列消息数据为内存地址传引用读队列/队尾写队列带拷贝LOS_QueueReadCopy、LOS_QueueWriteCopy从指定队列头节点读、往队列尾节点写入。队列消息数据为数据值传数值读队列/队首写队列LOS_QueueRead、LOS_QueueWriteHead从指定队列头节点读、往队列头节点写入。队列消息数据为内存地址传引用读队列/队首写队列带拷贝LOS_QueueReadCopy、LOS_QueueWriteHeadCopy从指定队列头节点读、往队列头节点写入。队列消息数据为数据值传数值 3.3 队列读取 我们知道有2个队列读取方法按指针地址读取的函数LOS_QueueRead()和按消息数值读取的函数LOS_QueueReadCopy()。我们先看下函数LOS_QueueRead()该函数的参数有4个队列编号queueID存放读取到的消息的缓冲区地址*bufferAddr存放读取到的消息的缓冲区大小bufferSize读队列消息的等待超时时间timeOut。代码如下我们分析下代码。 ⑴处校验传入参数队列编号不能超出限制传入的指针不能为空缓冲大小不能为0。如果timeout不为零不能在中断中读取队列。⑵处操作类型表示队首读取消息指针然后调用函数OsQueueOperate()进一步操作队列。 LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 queueID, VOID *bufferAddr, UINT32 bufferSize, UINT32 timeOut) {UINT32 ret;UINT32 operateType;⑴ ret OsQueueReadParameterCheck(queueID, bufferAddr, bufferSize, timeOut);if (ret ! LOS_OK) {return ret;}⑵ operateType OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD, OS_QUEUE_POINT);OsHookCall(LOS_HOOK_TYPE_QUEUE_READ, (LosQueueCB *)GET_QUEUE_HANDLE(queueID));return OsQueueOperate(queueID, operateType, bufferAddr, bufferSize, timeOut); }我们进一步分析下函数OsQueueOperate()这是是比较通用的封装读取写入都会调用这个函数我们以读取队列为例分析这个函数。⑴处获取队列的操作类型为读取操作。⑵处先调用函数OsQueueOperateParamCheck()进行参数校验校验队列是使用中的队列并对读写消息大小进行校验。⑶处如果可读数量为0无法读取时如果是零等待则返回错误码。如果当前锁任务调度跳出函数执行。否则执行⑷把当前任务放入队列的读取消息阻塞队列然后触发任务调度后续的代码暂时不再执行。如果可读的数量不为0可以继续读取时执行⑹处代码把可读数量减1然后继续执行⑺处代码读取队列。 等读取队列阻塞超时或者队列可以读取后继续执行⑸处的代码。如果是发生超时队列还不能读取更改任务状态跳出函数执行。如果队列可以读取了继续执行⑺处代码读取队列。⑻处在成功读取队列后如果有任务阻塞在写入队列则获取阻塞链表中的第一个任务resumedTask然后调用唤醒函数OsSchedTaskWake()把待恢复的任务放入就绪队列触发一次任务调度。如果无阻塞任务则把可写入的数量加1。 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 readWriteTmp !readWrite;UINT32 intSave LOS_IntLock();queueCB (LosQueueCB *)GET_QUEUE_HANDLE(queueID); ⑵ ret OsQueueOperateParamCheck(queueCB, operateType, bufferSize);if (ret ! LOS_OK) {goto QUEUE_END;}⑶ if (queueCB-readWriteableCnt[readWrite] 0) {if (timeOut LOS_NO_WAIT) {ret OS_QUEUE_IS_READ(operateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;goto QUEUE_END;}if (g_losTaskLock) {ret LOS_ERRNO_QUEUE_PEND_IN_LOCK;goto QUEUE_END;}LosTaskCB *runTsk (LosTaskCB *)g_losTask.runTask; ⑷ OsSchedTaskWait(queueCB-readWriteList[readWrite], timeOut);LOS_IntRestore(intSave);LOS_Schedule();intSave LOS_IntLock(); ⑸ if (runTsk-taskStatus OS_TASK_STATUS_TIMEOUT) {runTsk-taskStatus ~OS_TASK_STATUS_TIMEOUT;ret LOS_ERRNO_QUEUE_TIMEOUT;goto QUEUE_END;}} else { ⑹ queueCB-readWriteableCnt[readWrite]--;}⑺ OsQueueBufferOperate(queueCB, operateType, bufferAddr, bufferSize);⑻ if (!LOS_ListEmpty(queueCB-readWriteList[readWriteTmp])) {resumedTask OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(queueCB-readWriteList[readWriteTmp]));OsSchedTaskWake(resumedTask);LOS_IntRestore(intSave);LOS_Schedule();return LOS_OK;} else { ⑼ queueCB-readWriteableCnt[readWriteTmp];}QUEUE_END:LOS_IntRestore(intSave);return ret; }我们再继续看下函数OsQueueBufferOperate()是具体如何读取队列的。⑴处switch-case语句根据操作类型获取操作位置。对于⑵头部读取的情况先获取读取位置queuePosition。然后如果当前头节点位置.queueHead加1等于队列消息长度头节点位置.queueHead设置为0否则加1。对于⑶头部写入的情况如果当前头节点位置.queueHead等于0头节点位置.queueHead设置为队列消息长度减1即queueCB-queueLen - 1否则头节点位置.queueHead减1即可。然后获取要写入的位置queuePosition。对于⑷尾部写入的情况先获取写入位置queuePosition。然后如果当前尾节点位置.queueTail加1等于队列消息长度尾节点位置.queueTail设置为0否则加1。 ⑸处基于获取的队列读取位置获取队列消息节点queueNode。⑹处判断操作类型如果是按指针读写消息直接读取消息节点的数据写入指针对应的缓冲区*(UINT32 *)bufferAddr或直接把指针对应的缓冲区*(UINT32 *)bufferAddr数据写入消息节点即可。我们接着看如何按数数据读写消息⑺处代码用于读取数据消息。每个消息节点的后4个字节保存的是消息的长度首先获取消息的长度msgDataSize然后把消息内容读取到bufferAddr。再看看⑻处如何写入队列消息首先把消息内容写入到queueNode然后再把消息长度的内容写入到queueNode queueCB-queueSize - sizeof(UINT32)就是每个消息节点的后4字节。 static INLINE VOID OsQueueBufferOperate(LosQueueCB *queueCB, UINT32 operateType,VOID *bufferAddr, UINT32 *bufferSize) {UINT8 *queueNode NULL;UINT32 msgDataSize;UINT16 queuePosion;errno_t rc;/* get the queue position */ ⑴ switch (OS_QUEUE_OPERATE_GET(operateType)) {case OS_QUEUE_READ_HEAD: ⑵ queuePosion queueCB-queueHead;((queueCB-queueHead 1) queueCB-queueLen) ? (queueCB-queueHead 0) : (queueCB-queueHead);break;case OS_QUEUE_WRITE_HEAD: ⑶ (queueCB-queueHead 0) ? (queueCB-queueHead (queueCB-queueLen - 1)) : (--queueCB-queueHead);queuePosion queueCB-queueHead;break;case OS_QUEUE_WRITE_TAIL: ⑷ queuePosion queueCB-queueTail;((queueCB-queueTail 1) queueCB-queueLen) ? (queueCB-queueTail 0) : (queueCB-queueTail);break;default:PRINT_ERR(invalid queue operate type!\n);return;}⑸ queueNode (queueCB-queue[(queuePosion * (queueCB-queueSize))]);⑹ if (OS_QUEUE_IS_POINT(operateType)) {if (OS_QUEUE_IS_READ(operateType)) {*(UINT32 *)bufferAddr *(UINT32 *)(VOID *)queueNode;} else {*(UINT32 *)(VOID *)queueNode *(UINT32 *)bufferAddr; // change to pp when calling OsQueueOperate}} else { ⑺ if (OS_QUEUE_IS_READ(operateType)) {msgDataSize *((UINT32 *)(UINTPTR)((queueNode queueCB-queueSize) - sizeof(UINT32)));rc memcpy_s((VOID *)bufferAddr, *bufferSize, (VOID *)queueNode, msgDataSize);if (rc ! EOK) {PRINT_ERR(%s[%d] memcpy failed, error type %u\n, __FUNCTION__, __LINE__, rc);return;}*bufferSize msgDataSize;} else { ⑻ *((UINT32 *)(UINTPTR)((queueNode queueCB-queueSize) - sizeof(UINT32))) *bufferSize;rc memcpy_s((VOID *)queueNode, queueCB-queueSize, (VOID *)bufferAddr, *bufferSize);if (rc ! EOK) {PRINT_ERR(%s[%d] memcpy failed, error type %u\n, __FUNCTION__, __LINE__, rc);return;}}} }3.4 队列写入 我们知道有4个队列写入方法2个队尾写入2个队首写入分别包含按指针地址写入消息和按数值写入消息。LOS_QueueWrite()会调用LOS_QueueWriteCopy()LOS_QueueWriteHead()会调用LOS_QueueWriteHeadCopy()然后指定不同的操作类型后会进一步调用前文已经分析过的函数OsQueueOperate()。 小结 本文带领大家一起剖析了鸿蒙轻内核的队列模块的源代码包含队列的结构体、队列池初始化、队列创建删除、读写消息等。 经常有很多小伙伴抱怨说不知道学习鸿蒙开发哪些技术不知道需要重点掌握哪些鸿蒙应用开发知识点 为了能够帮助到大家能够有规划的学习这里特别整理了一套纯血版鸿蒙HarmonyOS Next全栈开发技术的学习路线包含了鸿蒙开发必掌握的核心知识要点内容有ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等鸿蒙HarmonyOS NEXT技术知识点。 《鸿蒙 (Harmony OS)开发学习手册》共计892页:https://gitcode.com/HarmonyOS_MN/733GH/overview 如何快速入门 1.基本概念 2.构建第一个ArkTS应用 3.…… 开发基础知识: 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.…… 鸿蒙开发面试真题含参考答案:https://gitcode.com/HarmonyOS_MN/733GH/overview OpenHarmony 开发环境搭建 《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview 搭建开发环境Windows 开发环境的搭建Ubuntu 开发环境搭建Linux 与 Windows 之间的文件共享……系统架构分析构建子系统启动流程子系统分布式任务调度子系统分布式通信子系统驱动子系统…… OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview
http://www.zqtcl.cn/news/814534/

相关文章:

  • 网站怎么赚钱的网站asp源码
  • 明星网站怎么设计新手怎么做网络销售
  • ps做网站72分辨率深鑫辉网站建设
  • 购物网站设计的目的html简单登录页面代码
  • 网站导航栏下载网页自助建站
  • 新手建立网站的步骤建设企业网站个人网银
  • 俄罗斯女孩制作论文网站wordpress和hexo
  • 南宁市网站设计wordpress主题安装教程
  • 网站取消备案怎样做国外电子商务网站
  • 学校建设网站费用申请青岛平台公司
  • 平面设计师个人网站怎样登录韵网网站
  • 怎么用eclipse做网站开发推广平台取名字
  • 深圳建网站服务商广东佛山建网站
  • 网站推广公司卓立海创英文网站建设需求
  • 无锡网站营销公司简介最专业网站建设公司首选
  • 中文网站建设小组ios开发者账号申请
  • 月熊志网站福州建网站 做网页
  • 不同的网站有不同的风格宁波设计网站公司
  • 学校网站制作平台电子政务门户网站建设代码
  • 产品推广的网站怎么做网站标题与关键词
  • 青蛙网站建设wordpress修改logo
  • 网站套餐方案引擎搜索对人类记忆的影响
  • 滨州市滨城区建设局网站扎金花网站怎么做
  • 网站开发中视屏怎样编辑到网页上常州建站公司模板
  • 视频涉台互联网网站怎么做1cpu0.5g服务器用来做网站
  • 营销型网站设计官网怎么做网站优化 sit
  • 怎样获得做网站的客户免费企业网站程序上传
  • 新闻排版设计用什么软件网站seo诊断分析
  • 手机网站端域名怎样做解析一诺摄影设计
  • 网站开发行业竞争大吗郑州百度推广代运营公司