队列:实用程序服务和数据结构
隊(duì)列:實(shí)用程序服務(wù)和數(shù)據(jù)結(jié)構(gòu)
Queues: utility services and data structures
隊(duì)列實(shí)用程序服務(wù)
Nucleus RTOS有四個(gè)API調(diào)用,它們提供與隊(duì)列相關(guān)的實(shí)用函數(shù):重置隊(duì)列、返回有關(guān)隊(duì)列的信息、返回應(yīng)用程序中的隊(duì)列數(shù)量以及返回指向應(yīng)用程序中所有隊(duì)列的指針。前三個(gè)在Nucleus SE中實(shí)現(xiàn)。
重置隊(duì)列
此API調(diào)用將隊(duì)列恢復(fù)到其未使用的初始狀態(tài)。隊(duì)列中存儲(chǔ)的所有消息都將丟失。隊(duì)列上掛起的所有任務(wù)都將恢復(fù),并收到返回代碼NUSE_queue_WAS_RESET。
Nucleus RTOS API Call for Resetting a Queue
Service call prototype:
STATUS NU_Reset_Queue(NU_QUEUE *queue;
Parameters:
queue – pointer to user-define queue control block
Returns:
NU_SUCCESS – the call was completed successfully
NU_INVALID_QUEUE – the queue
pointer is not valid
Nucleus SE API Call for Resetting a Queue
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
STATUS NUSE_Queue_Reset(NUSE_QUEUE queue);
Parameters:
queue – the index (ID) of the queue to be reset
Returns:
NUSE_SUCCESS – the call was completed successfully
NUSE_INVALID_QUEUE – the queue index is not valid
Nucleus SE Implementation of Queue Reset
在參數(shù)檢查之后,NUSE_Queue_Reset()API函數(shù)的最初部分代碼非常簡單。頭和尾索引以及隊(duì)列的消息計(jì)數(shù)都設(shè)置為零。
啟用阻塞時(shí),其他代碼負(fù)責(zé)喚醒任何掛起的任務(wù),因此:
while (NUSE_Queue_Blocking_Count[queue] != 0){ U8 index; /* check whether any tasks are blocked / / on this queue */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_QUEUE_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Queue_Blocking_Count[queue]–;}#if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK);#endif
隊(duì)列上掛起的每個(gè)任務(wù)都標(biāo)記為“就緒”,掛起返回代碼NUSE_queue_WAS_RESET。此過程完成后,如果正在使用優(yōu)先級(jí)調(diào)度程序,則會(huì)調(diào)用NUSE_Reschedule(),因?yàn)橐粋€(gè)或多個(gè)優(yōu)先級(jí)較高的任務(wù)可能已準(zhǔn)備就緒,需要允許其運(yùn)行。
隊(duì)列信息
此服務(wù)調(diào)用獲取有關(guān)隊(duì)列的信息選擇。Nucleus SE實(shí)現(xiàn)與Nucleus RTOS的不同之處在于,它返回的信息較少,因?yàn)椴恢С謱?duì)象命名、可變消息大小和掛起順序,并且可能無法啟用任務(wù)掛起。
Nucleus RTOS API Call for Queue Information
Service call prototype:
STATUS NU_Queue_Information(NU_QUEUE *queue, CHAR *name,
VOID **start_address,UNSIGNED *queue_size, UNSIGNED
*available,
UNSIGNED *messages, OPTION *message_type,
UNSIGNED *message_size, OPTION *suspend_type,
UNSIGNED *tasks_waiting, NU_TASK **first_task);
Parameters:
queue – pointer to the user-supplied queue control block
name – pointer to an 8-character
destination area for the message-queue’s name
start_address – a pointer to a
pointer, which will receive the address of the start of the queue’s data area
queue_size – a pointer to a
variable for holding the total number of UNSIGNED data
elements in the queue
available – a pointer to a
variable for holding the number of available UNSIGNED data
elements in the queue
messages – a pointer to a
variable for holding the number of messages currently in the queue
message_type – pointer to a
variable for holding the type of messages supported by the queue; valid message
types are NU_FIXED_SIZE and NU_ VARIABLE_SIZE
message_size – pointer to a
variable for holding the number of UNSIGNED data
elements in each queue message; if the queue supports variable-length messages,
this number is the maximum message size
suspend_type – pointer to a
variable for holding the task suspend type. Valid task suspend types are NU_FIFO and NU_PRIORITY
tasks_waiting – a pointer to a
variable which will receive the number of tasks suspended on this queue
first_task – a pointer to a task
pointer; the pointer of the first suspended task is placed in this task pointer
Returns:
NU_SUCCESS – the call was completed successfully
NU_INVALID_QUEUE – the queue
pointer is not valid
Nucleus
SE API Call for Queue Information
This API call supports the key functionality of the Nucleus RTOS
API.
Service call prototype:
STATUS
NUSE_Queue_Information(NUSE_QUEUE queue,
ADDR *start_address, U8 *queue_size, U8 *available, U8
*messages, U8 *tasks_waiting, NUSE_TASK *first_task);
Parameters:
queue – the index of the queue about which information is being
requested
start_address – a pointer to a
variable of type ADDR ,
which will receive the address of the start of the queue’s data area
queue_size – a pointer to a
variable of type U8 ,
which will receive the total number of messages for which the queue has capacity
available – a pointer to a
variable of type U8 ,
which will receive the number of messages for which the queue has currently
remaining capacity
messages – a pointer to a
variable of type U8 ,
which will receive the number of messages currently in the queue
tasks_waiting – a pointer to a
variable which will receive the number of tasks suspended on this queue
(nothing returned if task suspend is disabled)
first_task – a pointer to a
variable of type NUSE_TASK which
will receive the index of the first suspended task (nothing returned if task
suspend is disabled)
Returns:
NUSE_SUCCESS – the call was completed successfully
NUSE_INVALID_QUEUE – the queue
index is not valid
NUSE_INVALID_POINTER – one or
more of the pointer parameters is invalid
Nucleus
SE Implementation of Queue Information
The implementation of this API call is quite straightforward:
*start_address = NUSE_Queue_Data[queue];*queue_size = NUSE_Queue_Size[queue];*available = NUSE_Queue_Size[queue] - NUSE_Queue_Items[queue];*messages = NUSE_Queue_Items[queue];#if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Queue_Blocking_Count[queue]; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif
函數(shù)返回隊(duì)列狀態(tài)。然后,如果啟用了阻塞API調(diào)用,則返回等待的任務(wù)數(shù)和第一個(gè)任務(wù)的索引(否則這兩個(gè)參數(shù)設(shè)置為0)。
獲取隊(duì)列數(shù)
此服務(wù)調(diào)用返回應(yīng)用程序中配置的隊(duì)列數(shù)。在Nucleus RTOS中,這將隨時(shí)間而變化,返回的值將表示當(dāng)前的隊(duì)列數(shù),而在Nucleus SE中,返回的值在構(gòu)建時(shí)設(shè)置,不能更改。
Nucleus RTOS API Call for Queue Count
Service call prototype:
UNSIGNED NU_Established_Queues(VOID);
Parameters:
None
Returns:
The number of created queues in the system.
Nucleus SE API Call for Queue Count
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
U8 NUSE_Queue_Count(void);
Parameters:
None
Returns:
The number of configured queues in the application
隊(duì)列計(jì)數(shù)的Nucleus SE實(shí)現(xiàn)
這個(gè)API調(diào)用的實(shí)現(xiàn)非常簡單:返回#define symbol NUSE_QUEUE_NUMBER的值。
數(shù)據(jù)結(jié)構(gòu)
隊(duì)列使用五到六個(gè)數(shù)據(jù)結(jié)構(gòu)—全部在RAM和ROM中—與其他Nucleus SE對(duì)象一樣,這些數(shù)據(jù)結(jié)構(gòu)是一系列表,根據(jù)配置的隊(duì)列數(shù)量和選擇的選項(xiàng)進(jìn)行包含和標(biāo)注。
我強(qiáng)烈建議應(yīng)用程序代碼不要直接訪問這些數(shù)據(jù)結(jié)構(gòu),而是使用提供的API函數(shù)。這避免了與Nucleus SE未來版本的不兼容和不必要的副作用,并簡化了將應(yīng)用程序移植到Nucleus RTOS的過程。這里包含數(shù)據(jù)結(jié)構(gòu)的詳細(xì)信息,以便更容易地理解服務(wù)調(diào)用代碼的工作方式和調(diào)試。
內(nèi)核RAM數(shù)據(jù)
這些數(shù)據(jù)結(jié)構(gòu)包括:
NUSE_Queue_Head[]–這是一個(gè)U8類型的數(shù)組,每個(gè)配置的隊(duì)列有一個(gè)條目,它表示指向消息隊(duì)列前面的指針。它用作NUSE_Queue_Data[]中地址的索引(見下文)。
NUSE_Queue_Tail[]–這是一個(gè)U8類型的數(shù)組,每個(gè)配置的隊(duì)列有一個(gè)條目,它表示指向消息隊(duì)列末尾的指針。它用作NUSE_Queue_Data[]中地址的索引(見下文)。
NUSE_Queue_Items[]–這是一個(gè)U8類型的數(shù)組,每個(gè)配置的隊(duì)列有一個(gè)條目,表示隊(duì)列中當(dāng)前消息數(shù)的計(jì)數(shù)。這個(gè)數(shù)據(jù)可以說是多余的,因?yàn)樗闹悼梢詮膆ead和tail索引中派生出來,但是存儲(chǔ)計(jì)數(shù)可以簡化代碼。
NUSE_Queue_Blocking_Count[]–此類型的U8數(shù)組包含每個(gè)隊(duì)列上阻塞的任務(wù)數(shù)。此數(shù)組僅在啟用阻止API調(diào)用支持時(shí)存在。
當(dāng)Nucleus SE啟動(dòng)時(shí),這些數(shù)據(jù)結(jié)構(gòu)都由NUSE_Init_Queue()初始化為零。這是合乎邏輯的,因?yàn)樗鼘⒚總€(gè)隊(duì)列呈現(xiàn)為空(未使用)。未來的文章將全面描述Nucleus SE的啟動(dòng)過程。
以下是nuse_init.c文件中這些數(shù)據(jù)結(jié)構(gòu)的定義:
RAM U8 NUSE_Queue_Head[NUSE_QUEUE_NUMBER];RAM U8 NUSE_Queue_Tail[NUSE_QUEUE_NUMBER];RAM U8 NUSE_Queue_Items[NUSE_QUEUE_NUMBER];#if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Queue_Blocking_Count[NUSE_QUEUE_NUMBER];#endif
用戶RAM
用戶負(fù)責(zé)為每個(gè)配置的隊(duì)列提供一個(gè)RAM區(qū)域用于數(shù)據(jù)存儲(chǔ)。這個(gè)RAM區(qū)域的大小必須容納ADDR類型的數(shù)組,隊(duì)列中的每條消息都有一個(gè)條目。
ROM數(shù)據(jù)
這些數(shù)據(jù)結(jié)構(gòu)包括:
NUSE_Queue_Data[]–這是一個(gè)ADDR類型的數(shù)組,每個(gè)配置的隊(duì)列有一個(gè)條目,它表示每個(gè)隊(duì)列的數(shù)據(jù)區(qū)指針(在上面的用戶RAM中討論過)。
NUSE_Queue_Size[]–這是一個(gè)U8類型的數(shù)組,每個(gè)配置的隊(duì)列有一個(gè)條目,表示每個(gè)隊(duì)列可以容納的消息數(shù)。
這些數(shù)據(jù)結(jié)構(gòu)都在nuse_config.c中聲明和初始化(當(dāng)然是靜態(tài)的),因此:
ROM ADDR NUSE_Queue_Data[NUSE_QUEUE_NUMBER] ={ / addresses of queue data areas ------ /};ROM U8 NUSE_Queue_Size[NUSE_QUEUE_NUMBER] ={ / queue sizes ------ */};
Queue Data Footprint
Like all kernel objects in Nucleus SE, the amount of data memory
required for queues is readily predictable.
The ROM data footprint (in bytes) for all the queues in an
application may be computed thus:
NUSE_QUEUE_NUMBER * (sizeof(ADDR) + 1)
The kernel RAM data footprint (in bytes) for all the queues in
an application, when blocking API calls is enabled, may be computed thus:
NUSE_QUEUE_NUMBER* 3
Otherwise it is:
NUSE_QUEUE_NUMBER* 4
The amount of user RAM (in bytes) required for the queue with
index queue is:
NUSE_Queue_Size[queue]* sizeof(ADDR)
Unimplemented API Calls
Four queue API calls found in Nucleus RTOS are not implemented
in Nucleus SE:
Create Queue
This API call creates a queue. It is not needed with Nucleus SE,
as queues are created statically.
Service call prototype:
STATUS NU_Create_Queue(NU_QUEUE *queue, char *name,
VOID *start_address, UNSIGNED queue_size, OPTION
message_type, UNSIGNED message_size, OPTION suspend_type);
Parameters:
queue – pointer to a user-supplied queue control block; this
will be used as a “handle” for the queue in other API calls
name – pointers to a 7-character, null-terminated name for the queue
start_address – starting address for the queue
message_type – type of message
supported by the queue; may be NU_FIXED_SIZE or NU_VARIABLE_SIZE
message_size – if the queue supports fixed size messages, this parameter specifies the exact size of each message; otherwise, if the queue supports variable sized messages, this is the maximum message size suspend_type – specifies how
tasks suspend on the queue. Valid options for this parameter are NU_FIFOand NU_PRIORITY , which represent
First-In-First-Out (FIFO) and priority-order task suspension, respectively
Returns:
NU_SUCCESS – indicates successful completion of the service
NU_INVALID_QUEUE – indicates the
queue control block pointer is NULL or already in use
NU_INVALID_MEMORY – indicates the
memory area specified by the start_address is invalid
NU_INVALID_MESSAGE – indicates
that the message_type parameter is invalid
NU_INVALID_SIZE – indicates that
either the message size is greater than the queue size, or that the queue size or message size is zero
NU_INVALID_SUSPEND – indicates
that the suspend_type parameter is invalid
Delete Queue
This API call deletes a previously created queue. It is not needed with Nucleus SE, as queues are created statically and cannot be deleted.
Service call prototype:
STATUS NU_Delete_Queue(NU_QUEUE *queue);
Parameters:
queue – pointer to queue control block
Returns:
NU_SUCCESS – indicates successful completion of the service
NU_INVALID_QUEUE – indicates the
queue pointer is invalid
Queue Pointers
This API call builds a sequential list of pointers to all queues
in the system. It is not needed with Nucleus SE, as queues are identified by a simple index, not a pointer, and it would be redundant.
Service call prototype:
UNSIGNED NU_Queue_Pointers(NU_QUEUE **pointer_list,
UNSIGNED maximum_pointers);
Parameters:
pointer_list – pointer to an array of NU_QUEUE pointers;
this array will be filled with pointers to established queues in the system
maximum_pointers – the maximum
number of pointers to place in the array
Returns:
The number of NU_QUEUE pointers placed into the array
Broadcast to Queue
This API call broadcasts a message to all tasks waiting for a message from the specified queue. It is not implemented with Nucleus SE, as it would have added excessive complexity.
Service call prototype:
STATUS NU_Broadcast_To_Queue(NU_QUEUE *queue, VOID *message, UNSIGNED size, UNSIGNED suspend);
Parameters:
queue – pointer to queue control block
message – pointer to the broadcast message
size – the number of UNSIGNED data elements in the message. If the queue supports variable-length messages, this parameter must be
equal to or less than the message size supported by the queue. If the queue supports fixed-size messages, this parameter must be exactly the same as the message size supported by the queue
suspend – specifies whether or not to suspend the calling task if the queue is already full; valid options for this parameter are NU_NO_SUSPEND , NU_SUSPEND or a timeout value.
Returns:
NU_SUCCESS – indicates successful completion of the service
NU_INVALID_QUEUE – indicates the queue pointer is invalid
NU_INVALID_POINTER – indicates
that the message pointer is NULL
NU_INVALID_SIZE – Indicates that the message size specified is not compatible with the size specified when the queue was created
NU_INVALID_SUSPEND – indicates
that suspend attempted from a non-task thread
NU_QUEUE_FULL – indicates that
there is insufficient space in the queue for the message
NU_TIMEOUT – indicates the queue
is still full after the timeout has expired
NU_QUEUE_DELETED – queue was
deleted while task was suspended
NU_QUEUE_RESET – queue was reset
while the task was suspended
與Nucleus RTOS的兼容性
對(duì)于Nucleus SE的各個(gè)方面,我的目標(biāo)是盡可能保持與Nucleus RTOS的高級(jí)別應(yīng)用程序代碼兼容性。隊(duì)列也不例外,從用戶的角度來看,它們的實(shí)現(xiàn)方式與Nucleus RTOS中的方式大致相同。有一些不兼容的地方,我認(rèn)為這樣的不兼容是可以接受的,因?yàn)樯傻拇a更容易理解,或者更有可能提高內(nèi)存效率。否則,Nucleus RTOS API調(diào)用幾乎可以直接映射到Nucleus SE調(diào)用上。未來的一篇文章將包括關(guān)于為Nucleus RTOS用戶使用Nucleus SE的更多信息。
對(duì)象標(biāo)識(shí)符
在Nucleus RTOS中,所有對(duì)象都由具有特定數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu)(控制塊)來描述。指向此控制塊的指針用作隊(duì)列的標(biāo)識(shí)符。在Nucleus SE中,我決定需要一種不同的方法來提高內(nèi)存效率,所有的內(nèi)核對(duì)象都由RAM和/或ROM中的許多表來描述,這些表的大小由配置的每個(gè)對(duì)象類型的數(shù)量決定。特定對(duì)象的標(biāo)識(shí)符只是這些表的索引。因此,我將NUSE_QUEUE定義為等同于U8;此類型的變量(而不是指針)將用作隊(duì)列標(biāo)識(shí)符。這是一個(gè)小的不兼容性,如果代碼被移植到Nucleus RTOS或從Nucleus RTOS移植過來,就很容易處理這個(gè)問題。對(duì)象標(biāo)識(shí)符通常只是存儲(chǔ)和傳遞,而不是以任何方式操作。
Nucleus RTOS還支持隊(duì)列命名。這些名稱僅用于基于目標(biāo)的調(diào)試工具。為了節(jié)省內(nèi)存,我把它們從Nucleus SE中省略了。
消息大小和可變性
在Nucleus RTOS中,隊(duì)列可以配置為處理由任意數(shù)量的無符號(hào)數(shù)據(jù)元素組成的消息。在Nucleus SE中,隊(duì)列被簡化,只支持單個(gè)ADDR消息。管道在Nucleus SE中更為靈活,可能為某些應(yīng)用程序提供了替代隊(duì)列的有用方法;本系列的下兩篇文章將介紹管道。
Nucleus RTOS還支持具有可變大小消息的隊(duì)列,其中僅在創(chuàng)建時(shí)指定最大大小。Nucleus SE不支持可變大小的消息。
隊(duì)列大小
Nucleus SE中隊(duì)列中的消息數(shù)被限制為256條,因?yàn)樗兴饕兞亢统A慷际荱8類型。Nucleus RTOS不受此限制。
未實(shí)現(xiàn)的API調(diào)用
Nucleus RTOS支持10個(gè)服務(wù)調(diào)用來處理隊(duì)列。其中4個(gè)在Nucleus SE中沒有實(shí)現(xiàn)。
總結(jié)
以上是生活随笔為你收集整理的队列:实用程序服务和数据结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 管道:介绍和基本服务
- 下一篇: 嵌入式Linux的OTA更新,基础知识和