kernel-mini-basic-ipc-queue.md 16.3 KB
Newer Older
A
Annie_wang 已提交
1
# Queue
D
duangavin123 已提交
2

D
duangavin123 已提交
3 4 5 6 7 8
## Basic Concepts<a name="section5747112216469"></a>

A queue, also called a message queue, is a data structure used for communication between tasks. The queue receives messages of unfixed length from tasks or interrupts, and determines whether to store the transferred messages in the queue based on different APIs.

Tasks can read messages from a queue. When the queue has no messages, the tasks are suspended. When the queue has a new message, the suspended tasks are woken up and process the new message. Tasks can also write messages to the queue. When the queue is full, the write task is suspended. When there is an available message node in the queue, the suspended write task is woken up and writes a message.

A
annie_wangli 已提交
9
You can adjust the timeout period of the read queue and write queue to adjust the block mode of the read and write APIs. If the timeout period is set to **0** for the read queue and write queue, tasks will not be suspended and the API directly returns. This is the non-block mode. If the timeout period is greater than **0**, block mode is used.
D
duangavin123 已提交
10 11 12 13 14 15 16 17 18 19 20

An asynchronous processing mechanism is provided to allow messages in a queue not to be processed immediately. In addition, queues can be used to buffer messages and implement asynchronous task communication. Queues have the following features:

-   Messages are queued in first-in-first-out \(FIFO\) mode and can be read and written asynchronously.
-   Both the read queue and write queue support the timeout mechanism.
-   Each time a message is read, the message node becomes available.
-   The types of messages to be sent are determined by the parties involved in communication. Messages of different lengths \(not exceeding the message node size of the queue\) are allowed.
-   A task can receive messages from and send messages to any message queue.
-   Multiple tasks can receive messages from and send messages to the same queue.
-   When a queue is created, the required dynamic memory space is automatically allocated in the queue API.

A
Annie_wang 已提交
21
## Working Principles
D
duangavin123 已提交
22

A
Annie_wang 已提交
23
### Queue Control Block
D
duangavin123 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

```
/**
 * Data structure of the queue control block
  */
typedef struct 
{
    UINT8       *queue;                          /* Pointer to the memory space of queue messages */
    UINT16      queueState;                      /* Queue status*/
    UINT16      queueLen;                        /* Number of message nodes in a queue, that is, the queue length */
    UINT16      queueSize;                       /* Size of a message node */
    UINT16      queueID;                         /*Queue ID */
    UINT16      queueHead;                       /* Position of the message head node (array subscript)*/
    UINT16      queueTail;                       /* Position of the message tail node (array subscript) */
    UINT16      readWriteableCnt[OS_READWRITE_LEN];/* The array element with subscript 0 indicates the number of readable messages in a queue.
                                                    The element with subscript 1 indicates the number of writable messages in a queue. */
    LOS_DL_LIST readWriteList[OS_READWRITE_LEN];    /* A linked list of tasks waiting to read or write messages.
                                                    Subscript 0: list of tasks waiting to read messages. Subscript 1: list of tasks waiting to write messages. */
    LOS_DL_LIST memList;                         /* A linked list of memory blocks*/
} LosQueueCB;
```

Each queue control block contains information about the queue status.

-   **OS\_QUEUE\_UNUSED**: The queue is not in use.
-   **OS\_QUEUE\_INUSED**: The queue is in use.

### Working Principles<a name="section15384012164811"></a>

-   The queue ID is returned if a queue is created successfully.
A
annie_wangli 已提交
54 55 56 57
-   The queue control block contains **Head** and **Tail**, which indicate the storage status of messages in a queue. **Head** indicates the start position of occupied message nodes in the queue. **Tail** indicates the end position of the occupied message nodes and the start position of idle message nodes. When a queue is created, **Head** and **Tail** point to the start position of the queue.
-   When data is to be written to a queue, **readWriteableCnt\[1\]** is used to determine whether data can be written to the queue. If **readWriteableCnt\[1\]** is **0**, the queue is full and data cannot be written to it. Data can be written to the head node or tail node of a queue. To write data to the tail node, locate the start idle message node based on **Tail** and write data to it. If **Tail** is pointing to the tail of the queue, the rewind mode is used. To write data to the head node, locate previous node based on **Head** and write data to it. If **Head** is pointing to the start position of the queue, the rewind mode is used.
-   When a queue is to be read, **readWriteableCnt\[0\]** is used to determine whether the queue has messages to read. Reading an idle queue \(**readWriteableCnt\[0\]** is **0**\) will cause task suspension. If the queue has messages to read, the system locates the first node to which data is written based on **Head** and read the message from the node. If **Head** is pointing to the tail of the queue, the rewind mode is used.
-   When a queue is to be deleted, the system locates the queue based on the queue ID, sets the queue status to **OS\_QUEUE\_UNUSED**, sets the queue control block to the initial state, and releases the memory occupied by the queue.
D
duangavin123 已提交
58

A
annie_wangli 已提交
59
**Figure 1** Reading and writing data in a queue<a name="fig1343517592468"></a> 
D
duangavin123 已提交
60 61 62 63
![](figures/reading-and-writing-data-in-a-queue.png "reading-and-writing-data-in-a-queue")

The preceding figure illustrates how to write data to the tail node only. Writing data to the head node is similar.

A
Annie_wang 已提交
64
## Available APIs
D
duangavin123 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

<a name="table10903105695114"></a>
<table><thead align="left"><tr id="row1293645645110"><th class="cellrowborder" valign="top" width="23.56%" id="mcps1.1.4.1.1"><p id="p59361562512"><a name="p59361562512"></a><a name="p59361562512"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="24.29%" id="mcps1.1.4.1.2"><p id="p1393665645118"><a name="p1393665645118"></a><a name="p1393665645118"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="52.15%" id="mcps1.1.4.1.3"><p id="p119363564516"><a name="p119363564516"></a><a name="p119363564516"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1693665613516"><td class="cellrowborder" rowspan="2" valign="top" width="23.56%" headers="mcps1.1.4.1.1 "><p id="p193675615514"><a name="p193675615514"></a><a name="p193675615514"></a>Creating or deleting a message queue</p>
</td>
<td class="cellrowborder" valign="top" width="24.29%" headers="mcps1.1.4.1.2 "><p id="p11936115612514"><a name="p11936115612514"></a><a name="p11936115612514"></a>LOS_QueueCreate</p>
</td>
<td class="cellrowborder" valign="top" width="52.15%" headers="mcps1.1.4.1.3 "><p id="p1593620562517"><a name="p1593620562517"></a><a name="p1593620562517"></a>Creates a message queue. The system dynamically allocates the queue space.</p>
</td>
</tr>
<tr id="row79361156175113"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p893615567517"><a name="p893615567517"></a><a name="p893615567517"></a>LOS_QueueDelete</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p4936155695111"><a name="p4936155695111"></a><a name="p4936155695111"></a>Deletes the specified queue based on the queue ID. </p>
</td>
</tr>
<tr id="row093614566519"><td class="cellrowborder" rowspan="3" valign="top" width="23.56%" headers="mcps1.1.4.1.1 "><p id="p1593685614513"><a name="p1593685614513"></a><a name="p1593685614513"></a>Reading or writing data in a queue (without the content contained in the address)</p>
</td>
<td class="cellrowborder" valign="top" width="24.29%" headers="mcps1.1.4.1.2 "><p id="p6936556155118"><a name="p6936556155118"></a><a name="p6936556155118"></a>LOS_QueueRead</p>
</td>
<td class="cellrowborder" valign="top" width="52.15%" headers="mcps1.1.4.1.3 "><p id="p11936556155118"><a name="p11936556155118"></a><a name="p11936556155118"></a>Reads data in the head node of the specified queue. The data in the queue node is an address.</p>
</td>
</tr>
<tr id="row199369565518"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p393655620513"><a name="p393655620513"></a><a name="p393655620513"></a>LOS_QueueWrite</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p12936256175120"><a name="p12936256175120"></a><a name="p12936256175120"></a>Writes the value of the input parameter <strong id="b2093863854458"><a name="b2093863854458"></a><a name="b2093863854458"></a>bufferAddr</strong> (buffer address) to the tail node of the specified queue.</p>
</td>
</tr>
<tr id="row1293615635114"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p893625665119"><a name="p893625665119"></a><a name="p893625665119"></a>LOS_QueueWriteHead</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p193620566515"><a name="p193620566515"></a><a name="p193620566515"></a>Writes the value of the input parameter <strong id="b2553137414458"><a name="b2553137414458"></a><a name="b2553137414458"></a>bufferAddr</strong> (buffer address) to the head node of the specified queue.</p>
</td>
</tr>
<tr id="row593675635117"><td class="cellrowborder" rowspan="3" valign="top" width="23.56%" headers="mcps1.1.4.1.1 "><p id="p293675615111"><a name="p293675615111"></a><a name="p293675615111"></a>Reading or writing in a queue (with the content contained in the address)</p>
</td>
<td class="cellrowborder" valign="top" width="24.29%" headers="mcps1.1.4.1.2 "><p id="p14936356155113"><a name="p14936356155113"></a><a name="p14936356155113"></a>LOS_QueueReadCopy</p>
</td>
<td class="cellrowborder" valign="top" width="52.15%" headers="mcps1.1.4.1.3 "><p id="p11936155616510"><a name="p11936155616510"></a><a name="p11936155616510"></a>Reads data from the head node of the specified queue.</p>
</td>
</tr>
<tr id="row093619569510"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p179361256175117"><a name="p179361256175117"></a><a name="p179361256175117"></a>LOS_QueueWriteCopy</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p6936155616515"><a name="p6936155616515"></a><a name="p6936155616515"></a>Writes the data saved in the input parameter <strong id="b13905064014458"><a name="b13905064014458"></a><a name="b13905064014458"></a>bufferAddr</strong> to the tail node of the specified queue.</p>
</td>
</tr>
<tr id="row16936856185111"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p49361156195113"><a name="p49361156195113"></a><a name="p49361156195113"></a>LOS_QueueWriteHeadCopy</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p1193625675116"><a name="p1193625675116"></a><a name="p1193625675116"></a>Writes the data saved in the input parameter <strong id="b1312795384458"><a name="b1312795384458"></a><a name="b1312795384458"></a>bufferAddr</strong> to the head node of the specified queue.</p>
</td>
</tr>
<tr id="row1936756155114"><td class="cellrowborder" valign="top" width="23.56%" headers="mcps1.1.4.1.1 "><p id="p149371956105114"><a name="p149371956105114"></a><a name="p149371956105114"></a>Obtaining queue information</p>
</td>
<td class="cellrowborder" valign="top" width="24.29%" headers="mcps1.1.4.1.2 "><p id="p7937145613516"><a name="p7937145613516"></a><a name="p7937145613516"></a>LOS_QueueInfoGet</p>
</td>
<td class="cellrowborder" valign="top" width="52.15%" headers="mcps1.1.4.1.3 "><p id="p19371356175110"><a name="p19371356175110"></a><a name="p19371356175110"></a>Obtains information about the specified queue, including the queue ID, queue length, message node size, head node, tail node, number of readable nodes, number of writable nodes, tasks waiting for read operations, and tasks waiting for write operations.</p>
</td>
</tr>
</tbody>
</table>

A
Annie_wang 已提交
131
## How to Develop
D
duangavin123 已提交
132

A
annie_wangli 已提交
133 134 135 136 137
1.  Call **LOS\_QueueCreate** to create a queue. The queue ID is returned when the queue is created.
2.  Call **LOS\_QueueWrite** or **LOS\_QueueWriteCopy** to write messages to the queue.
3.  Call **LOS\_QueueRead** or **LOS\_QueueReadCopy** to read messages from the queue.
4.  Call **LOS\_QueueInfoGet** to obtain queue information.
5.  Call **LOS\_QueueDelete** to delete the queue.
D
duangavin123 已提交
138

A
Annie_wang 已提交
139
>![](../public_sys-resources/icon-note.gif) **NOTE**<br/> 
D
duangavin123 已提交
140 141
>-   The maximum number of queues supported by the system is the total number of queue resources of the system, not the number of queue resources available to users. For example, if the system software timer occupies one more queue resource, the number of queue resources available to users decreases by one.
>-   The input parameters queue name and flags passed when a queue is created are reserved for future use.
A
annie_wangli 已提交
142 143 144 145 146
>-   The input parameter **timeOut** in the queue interface function is relative time.
>-   **LOS\_QueueReadCopy**, **LOS\_QueueWriteCopy**, and **LOS\_QueueWriteHeadCopy** are a group of APIs that must be used together. **LOS\_QueueRead**, **LOS\_QueueWrite**, and **LOS\_QueueWriteHead** are a group of APIs that must be used together.
>-   As **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are used to manage data addresses, you must ensure that the memory directed by the pointer obtained by calling **LOS\_QueueRead** is not modified or released abnormally when the queue is being read. Otherwise, unpredictable results may occur.
>-   If the input parameter **bufferSize** in **LOS\_QueueReadCopy** is less than the length of the message, the message will be truncated.
>-   **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are called to manage data addresses, which means that the actual data read or written is pointer data. Therefore, before using these APIs, ensure that the message node size is the pointer length during queue creation, to avoid waste and read failures.
D
duangavin123 已提交
147

A
Annie_wang 已提交
148
## Development Example
D
duangavin123 已提交
149

A
Annie_wang 已提交
150
### Example Description
D
duangavin123 已提交
151 152 153

Create a queue and two tasks. Enable task 1 to call the queue write API to send messages, and enable task 2 to receive messages by calling the queue read API.

A
annie_wangli 已提交
154 155 156 157 158
1.  Create task 1 and task 2 by calling **LOS\_TaskCreate**.
2.  Create a message queue by calling **LOS\_QueueCreate**.
3.  Enable messages to be sent in task 1 by calling **SendEntry**.
4.  Enable messages to be received in task 2 by calling **RecvEntry**.
5.  Call **LOS\_QueueDelete** to delete the queue.
D
duangavin123 已提交
159

A
Annie_wang 已提交
160
### Sample Code
D
duangavin123 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

The sample code is as follows:

```
#include "los_task.h"
#include "los_queue.h"
static UINT32 g_queue;
#define BUFFER_LEN 50

VOID SendEntry(VOID)
{
    UINT32 ret = 0;
    CHAR abuf[] = "test message";
    UINT32 len = sizeof(abuf);

    ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0);
    if(ret != LOS_OK) {
A
Annie_wang 已提交
178
        printf("Failed to send the message, error: %x\n", ret);
D
duangavin123 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191
    }
}

VOID RecvEntry(VOID)
{
    UINT32 ret = 0;
    CHAR readBuf[BUFFER_LEN] = {0};
    UINT32 readLen = BUFFER_LEN;

   // Sleep for 1s.
    usleep(1000000);
    ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0);
    if(ret != LOS_OK) {
A
Annie_wang 已提交
192
        printf("Failed to receive the message, error: %x\n", ret);
D
duangavin123 已提交
193 194 195 196 197 198
    }

    printf("recv message: %s\n", readBuf);

    ret = LOS_QueueDelete(g_queue);
    if(ret != LOS_OK) {
A
Annie_wang 已提交
199
        printf("Failed to delete the queue, error: %x\n", ret);
D
duangavin123 已提交
200 201
    }

A
Annie_wang 已提交
202
    printf("Deleted the queue successfully.\n");
D
duangavin123 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
}

UINT32 ExampleQueue(VOID)
{
    printf("start queue example.\n");
    UINT32 ret = 0;
    UINT32 task1, task2;
    TSK_INIT_PARAM_S initParam = {0};

    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry;
    initParam.usTaskPrio = 9;
    initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    initParam.pcName = "SendQueue";

    LOS_TaskLock();
    ret = LOS_TaskCreate(&task1, &initParam);
    if(ret != LOS_OK) {
A
Annie_wang 已提交
220
        printf("Failed to create task1, error: %x\n", ret);
D
duangavin123 已提交
221 222 223 224 225 226 227 228
        return ret;
    }

    initParam.pcName = "RecvQueue";
    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry;
    initParam.usTaskPrio = 10;
    ret = LOS_TaskCreate(&task2, &initParam);
    if(ret != LOS_OK) {
A
Annie_wang 已提交
229
        printf("Failed to create task2, error: %x\n", ret);
D
duangavin123 已提交
230 231 232 233 234
        return ret;
    }

    ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50);
    if(ret != LOS_OK) {
A
Annie_wang 已提交
235
        printf("Failed to create the queue, error: %x\n", ret);
D
duangavin123 已提交
236 237
    }

A
Annie_wang 已提交
238
    printf("Created the queue successfully.\n");
D
duangavin123 已提交
239 240 241 242 243
    LOS_TaskUnlock();
    return ret;
}
```

A
Annie_wang 已提交
244
### Verification
D
duangavin123 已提交
245 246 247 248 249 250 251 252 253 254

The development is successful if the return result is as follows:

```
start queue example.
create the queue success.
recv message: test message.
delete the queue success.
```