1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          queue什么意思(消息隊列Queue的含義和作用)

          來源:互聯網轉載 時間:2024-05-13 08:22:01

          隊列(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,其他結構體成員見注釋部分。

          typedefstruct{UINT8*queue;/**<隊列內存空間的指針*/UINT16queueState;/**<隊列的使用狀態*/UINT16queueLen;/**<隊列長度,即消息數量*/UINT16queueSize;/**<消息節點大小*/UINT16queueID;/**<隊列編號*/UINT16queueHead;/**<消息頭節點位置*/UINT16queueTail;/**<消息尾節點位置*/UINT16readWriteableCnt[OS_READWRITE_LEN];/**<2維數組,可讀、可寫的消息數量,0:可讀,1:可寫*/LOS_DL_LISTreadWriteList[OS_READWRITE_LEN];/**<2維雙向鏈表數組,阻塞讀、寫任務的雙向鏈表,0:讀鏈表,1:寫鏈表*/LOS_DL_LISTmemList;/**<內存節點雙向鏈表*/}LosQueueCB;

          1.2 隊列常用宏定義

          系統支持創建多少隊列是根據開發板情況使用宏LOSCFG_BASE_IPC_QUEUE_LIMIT定義的,每一個隊列queueID是queueID類型的,取值為[0,LOSCFG_BASE_IPC_QUEUE_LIMIT),表示隊列池中各個隊列的編號。

          ⑴處的宏從隊列池中獲取指定隊列編號QueueID對應的隊列控制塊。⑵處根據雙向鏈表節點readWriteList[OS_QUEUE_WRITE]獲取隊列控制塊內存地址。

          ⑴#defineGET_QUEUE_HANDLE(QueueID)(((LosQueueCB*)g_allQueue)+(QueueID))⑵#defineGET_QUEUE_LIST(ptr)LOS_DL_LIST_ENTRY(ptr,LosQueueCB,readWriteList[OS_QUEUE_WRITE])

          另外,隊列中還提供了比較重要的隊列讀取消息操作相關的枚舉和宏。枚舉QueueReadWrite區分隊列的讀和寫,枚舉QueueHeadTail區分隊列的首和尾,枚舉QueuePointOrNot區分讀寫消息時是使用值還是指針。

          隊列的操作類型使用3比特位的數字來表示,見宏OS_QUEUE_OPERATE_TYPE的定義,其中高1位表示讀寫數值還是讀寫指針地址,中1位表示隊首還是隊尾,低1位表示讀取還是寫入。枚舉和宏的定義如下:

          typedefenum{OS_QUEUE_READ,OS_QUEUE_WRITE}QueueReadWrite;typedefenum{OS_QUEUE_HEAD,OS_QUEUE_TAIL}QueueHeadTail;typedefenum{OS_QUEUE_NOT_POINT,OS_QUEUE_POINT}QueuePointOrNot;#defineOS_QUEUE_OPERATE_TYPE(ReadOrWrite,HeadOrTail,PointOrNot)\(((UINT32)(PointOrNot)<<2)|((UINT32)(HeadOrTail)<<1)|(ReadOrWrite))#defineOS_QUEUE_READ_WRITE_GET(type)((type)&(0x01))#defineOS_QUEUE_READ_HEAD(OS_QUEUE_READ|(OS_QUEUE_HEAD<<1))#defineOS_QUEUE_READ_TAIL(OS_QUEUE_READ|(OS_QUEUE_TAIL<<1))#defineOS_QUEUE_WRITE_HEAD(OS_QUEUE_WRITE|(OS_QUEUE_HEAD<<1))#defineOS_QUEUE_WRITE_TAIL(OS_QUEUE_WRITE|(OS_QUEUE_TAIL<<1))#defineOS_QUEUE_OPERATE_GET(type)((type)&(0x03))#defineOS_QUEUE_IS_POINT(type)((type)&(0x04))#defineOS_QUEUE_IS_READ(type)(OS_QUEUE_READ_WRITE_GET(type)==OS_QUEUE_READ)#defineOS_QUEUE_IS_WRITE(type)(OS_QUEUE_READ_WRITE_GET(type)==OS_QUEUE_WRITE)#defineOS_READWRITE_LEN2

          2、隊列初始化

          隊列在內核中默認開啟,用戶可以通過宏LOSCFG_BASE_IPC_QUEUE進行關閉。開啟隊列的情況下,在系統啟動時,在kernel\src\los_init.c中調用OsQueueInit()進行隊列模塊初始化。下面,我們分析下隊列初始化的代碼。

          ⑴為隊列申請內存,如果申請失敗,則返回錯誤。⑵初始化雙向循環鏈表g_freeQueueList,維護未使用的隊列。⑶循環每一個隊列進行初始化,為每一個隊列節點指定索引queueID,并把隊列節點插入未使用隊列雙向鏈表g_freeQueueList。代碼上可以看出,掛在未使用隊列雙向鏈表上的節點是每個隊列控制塊的寫阻塞任務鏈表節點.readWriteList[OS_QUEUE_WRITE]。

          LITE_OS_SEC_TEXT_INITUINT32OsQueueInit(VOID){LosQueueCB*queueNode=NULL;UINT16index;if(LOSCFG_BASE_IPC_QUEUE_LIMIT==0){returnLOS_ERRNO_QUEUE_MAXNUM_ZERO;}⑴g_allQueue=(LosQueueCB*)LOS_MemAlloc(m_aucSysMem0,LOSCFG_BASE_IPC_QUEUE_LIMIT*sizeof(LosQueueCB));if(g_allQueue==NULL){returnLOS_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]);}returnLOS_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_INITUINT32LOS_QueueCreate(char*queueName,UINT16len,UINT32*queueID,UINT32flags,UINT16maxMsgSize){LosQueueCB*queueCB=NULL;UINT32intSave;LOS_DL_LIST*unusedQueue=NULL;UINT8*queue=NULL;UINT16msgSize;(VOID)queueName;(VOID)flags;⑴if(queueID==NULL){returnLOS_ERRNO_QUEUE_CREAT_PTR_NULL;}if(maxMsgSize>(OS_NULL_SHORT-sizeof(UINT32))){returnLOS_ERRNO_QUEUE_SIZE_TOO_BIG;}if((len==0)||(maxMsgSize==0)){returnLOS_ERRNO_QUEUE_PARA_ISZERO;}⑵msgSize=maxMsgSize+sizeof(UINT32);/*Memoryallocationistime-consuming,toshortenthetimeofdisableinterrupt,movethememoryallocationtohere.*/⑶queue=(UINT8*)LOS_MemAlloc(m_aucSysMem0,len*msgSize);if(queue==NULL){returnLOS_ERRNO_QUEUE_CREATE_NO_MEMORY;}intSave=LOS_IntLock();⑷if(LOS_ListEmpty(&g_freeQueueList)){LOS_IntRestore(intSave);(VOID)LOS_MemFree(m_aucSysMem0,queue);returnLOS_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);returnLOS_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_INITUINT32LOS_QueueDelete(UINT32queueID){LosQueueCB*queueCB=NULL;UINT8*queue=NULL;UINT32intSave;UINT32ret;⑴if(queueID>=LOSCFG_BASE_IPC_QUEUE_LIMIT){returnLOS_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;gotoQUEUE_END;}⑶if(!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_READ])){ret=LOS_ERRNO_QUEUE_IN_TSKUSE;gotoQUEUE_END;}if(!LOS_ListEmpty(&queueCB->readWriteList[OS_QUEUE_WRITE])){ret=LOS_ERRNO_QUEUE_IN_TSKUSE;gotoQUEUE_END;}if(!LOS_ListEmpty(&queueCB->memList)){ret=LOS_ERRNO_QUEUE_IN_TSKUSE;gotoQUEUE_END;}⑷if((queueCB->readWriteableCnt[OS_QUEUE_WRITE]+queueCB->readWriteableCnt[OS_QUEUE_READ])!=queueCB->queueLen){ret=LOS_ERRNO_QUEUE_IN_TSKWRITE;gotoQUEUE_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);returnret;QUEUE_END:LOS_IntRestore(intSave);returnret;}

          下面就來看看隊列的讀寫,有2點需要注意:

          • 隊首、隊尾的讀寫

          只支持隊首讀取,不能隊尾讀取,否則就不算隊列了。除了正常的隊尾寫消息外,還提供插隊機制,支持從隊首寫入。

          • 隊列消息數據內容

          往隊列中寫入的消息的類型有2種,即支持按地址寫入和按值寫入(帶拷貝)。按哪種類型寫入,就需要配對的按相應的類型去讀取。

          隊列讀取接口的類別,歸納如下:

          3.3 隊列讀取

          我們知道有2個隊列讀取方法,按指針地址讀取的函數LOS_QueueRead()和按消息數值讀取的函數LOS_QueueReadCopy()。我們先看下函數LOS_QueueRead(),該函數的參數有4個,隊列編號queueID,存放讀取到的消息的緩沖區地址*bufferAddr,存放讀取到的消息的緩沖區大小bufferSize,讀隊列消息的等待超時時間timeOut。代碼如下,我們分析下代碼。

          ⑴處校驗傳入參數,隊列編號不能超出限制,傳入的指針不能為空,緩沖大小不能為0。如果timeout不為零,不能在中斷中讀取隊列。⑵處操作類型表示隊首讀取消息指針,然后調用函數OsQueueOperate()進一步操作隊列。

          LITE_OS_SEC_TEXTUINT32LOS_QueueRead(UINT32queueID,VOID*bufferAddr,UINT32bufferSize,UINT32timeOut){UINT32ret;UINT32operateType;⑴ret=OsQueueReadParameterCheck(queueID,bufferAddr,&bufferSize,timeOut);if(ret!=LOS_OK){returnret;}⑵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));returnOsQueueOperate(queueID,operateType,bufferAddr,&bufferSize,timeOut);}

          我們進一步分析下函數OsQueueOperate(),這是是比較通用的封裝,讀取,寫入都會調用這個函數,我們以讀取隊列為例分析這個函數。⑴處獲取隊列的操作類型,為讀取操作。⑵處先調用函數OsQueueOperateParamCheck()進行參數校驗,校驗隊列是使用中的隊列,并對讀寫消息大小進行校驗。⑶處如果可讀數量為0,無法讀取時,如果是零等待則返回錯誤碼。如果當前鎖任務調度,跳出函數執行。否則,執行⑷把當前任務放入隊列的讀取消息阻塞隊列,然后觸發任務調度,后續的代碼暫時不再執行。如果可讀的數量不為0,可以繼續讀取時,執行⑹處代碼把可讀數量減1,然后繼續執行⑺處代碼讀取隊列。

          等讀取隊列阻塞超時,或者隊列可以讀取后,繼續執行⑸處的代碼。如果是發生超時,隊列還不能讀取,更改任務狀態,跳出函數執行。如果隊列可以讀取了,繼續執行⑺處代碼讀取隊列。⑻處在成功讀取隊列后,如果有任務阻塞在寫入隊列,則獲取阻塞鏈表中的第一個任務resumedTask,然后調用喚醒函數OsSchedTaskWake()把待恢復的任務放入就緒隊列,觸發一次任務調度。如果無阻塞任務,則把可寫入的數量加1。

          UINT32OsQueueOperate(UINT32queueID,UINT32operateType,VOID*bufferAddr,UINT32*bufferSize,UINT32timeOut){LosQueueCB*queueCB=NULL;LosTaskCB*resumedTask=NULL;UINT32ret;⑴UINT32readWrite=OS_QUEUE_READ_WRITE_GET(operateType);UINT32readWriteTmp=!readWrite;UINT32intSave=LOS_IntLock();queueCB=(LosQueueCB*)GET_QUEUE_HANDLE(queueID);⑵ret=OsQueueOperateParamCheck(queueCB,operateType,bufferSize);if(ret!=LOS_OK){gotoQUEUE_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;gotoQUEUE_END;}if(g_losTaskLock){ret=LOS_ERRNO_QUEUE_PEND_IN_LOCK;gotoQUEUE_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;gotoQUEUE_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();returnLOS_OK;}else{⑼queueCB->readWriteableCnt[readWriteTmp]++;}QUEUE_END:LOS_IntRestore(intSave);returnret;}

          我們再繼續看下函數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字節。

          staticINLINEVOIDOsQueueBufferOperate(LosQueueCB*queueCB,UINT32operateType,VOID*bufferAddr,UINT32*bufferSize){UINT8*queueNode=NULL;UINT32msgDataSize;UINT16queuePosion;errno_trc;/*getthequeueposition*/⑴switch(OS_QUEUE_OPERATE_GET(operateType)){caseoS_QUEUE_READ_HEAD:⑵queuePosion=queueCB->queueHead;((queueCB->queueHead+1)==queueCB->queueLen)?(queueCB->queueHead=0):(queueCB->queueHead++);break;caseOS_QUEUE_WRITE_HEAD:⑶(queueCB->queueHead==0)?(queueCB->queueHead=(queueCB->queueLen-1)):(--queueCB->queueHead);queuePosion=queueCB->queueHead;break;caseOS_QUEUE_WRITE_TAIL:⑷queuePosion=queueCB->queueTail;((queueCB->queueTail+1)==queueCB->queueLen)?(queueCB->queueTail=0):(queueCB->queueTail++);break;default:PRINT_ERR("invalidqueueoperatetype!\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;//changetoppwhencallingOsQueueOperate}}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]memcpyfailed,errortype=%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]memcpyfailed,errortype=%u\n",__FUNCTION__,__LINE__,rc);return;}}}}

          3.4 隊列寫入

          我們知道,有4個隊列寫入方法,2個隊尾寫入,2個隊首寫入,分別包含按指針地址寫入消息和按數值寫入消息。LOS_QueueWrite()會調用LOS_QueueWriteCopy(),LOS_QueueWriteHead()會調用LOS_QueueWriteHeadCopy(),然后指定不同的操作類型后,會進一步調用前文已經分析過的函數OsQueueOperate()。

          到此,關于“消息隊列Queue的含義和作用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注本站網站,小編會繼續努力為大家帶來更多實用的文章!

          標簽:queue什么意思-

          c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...

          2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...

          :喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...

          如果主要在國內消費,那么就不需要申請外資銀行的信用卡,但是對于那些經常出國的商旅人士或者是留學生來說,申請外資信用卡也是非常有必要的,那么相比較于國內銀行所推出的信用卡來說,外資銀行信用卡申請哪家好批卡?使用外資銀行信用卡看征信嗎?隨小編了解一下。目前我們常見的外資銀行主要有四家:匯豐、渣打、花旗和東亞銀行,這幾家外資銀行都有自己的信用卡產品,匯豐銀行主要有生活、旅行、卓越理財信用卡,渣打銀行只有...

          城鎮化的概念城鎮化是一個含義廣泛的概念。狹義上,它一般指人口城市化,即在一定時期內,城市數量和規模不斷增加,城市人口不斷聚集的過程。其本質含義是人類已經進入了工業社會時代,社會經濟的發展導致了農業活動比重的逐漸下降和非農業活動比重的逐漸增加。隨著經濟結構的變化,農村人口逐漸減少,城市人口比例穩步上升,居住區的外觀和人們的生活方式逐漸轉變和強化為城市性質。城鎮化率計算公式根據國家統計局,城市化率=城...

          (資料圖片僅供參考)據九派新聞,今年5月,柳智宇到一家心理咨詢公司任職,作為事業部部長,帶領十余人的小團隊,開發心理學課程。剛加入團隊,公司承諾給他3萬月薪,他嫌多,主動要求降到2萬,和其他員工一樣,“扣完稅1萬多,我不買房、不買車,更不想生孩子,你說我要那么多錢干啥?還不如多奉獻給大家。”他希望團隊早日實現收支平衡,希望大家能夠獲得自由,不管是精神上的還是經濟上的。據百度...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>