第12篇 zephyr 數據傳遞之STACK

目錄

摘要

1 概念

2 實現

2.1 定義一個stack

2.2 入棧

2.3 出棧

3 參考鏈接


本學筆記基於zephyr 工程版本 2.2.99,主機環境爲ubuntu18.04,開發平臺 nrf52840dk_nrf52840

摘要

stack是一個內核對象,它實現了後進先出隊列( last in, first out),允許線程和ISR添加或移除有限個整數值。

1 概念

任意個數的stack可以被定義,引用Stack時,使用的是Stack定義的內存地址,同樣只要你的內存允許,就可以隨便定義。

Stack有下面關鍵屬性:

一個整數值的queue,用於存儲加入Stack並且還沒有被移除的數據項。queue是通過stack_data_t類型值得一個數組來實現的,並且必須是字對齊。stack_data_t類型和cpu的word大小是一致的,一般是4個字節或者8個字節。

maximum quantity 加入隊列數組的數值的最大個數。

stack使用之前必須被初始化,初始化會將queue設置爲空。

一個數據值可以被ISR或者線程添加到stack,如果有等待線程存在,這個值會直接的傳給線程,而不是先加入queue再取出然後再給等待的線程。其他情況這個值會被添加到LIFO類型的queue。當stack中的隊列達到最大值,如果再繼續向stack中添加數據項,內核是不去檢測的。將導致一個未定義的行爲。類似於棧溢出了。

一個數據向可以被線程移除(取出),如果線程從一個沒有數據項的stack中取數據,那麼線程會進入等待,直到有數據項可以從stack中讀出。多個線程可以同時的訪問一個空的stack,當有數據項添加到stack中,優先級最高,等待時間最長的線程將先獲得數據項。

內核也允許在isr中去取出stack中的數據項,但是stack爲控制,isr不要嘗試去等待。

2 實現

2.1 定義一個stack

使用struct k_stack類型去定義stack變量,k_stack_init()或者k_stack_alloc_init()去初始化這個stack。使用這個k_stack_alloc_init()函數初始化的時候,一個緩衝區不用被提供,緩衝區可以的從線程內存池中分配。

下面代碼,定義並初始化一個可以保存10個數據的空stack:

#define MAX_ITEMS 10

stack_data_t my_stack_array[MAX_ITEMS];
struct k_stack my_stack;

k_stack_init(&my_stack, my_stack_array, MAX_ITEMS);

或者可以在編譯時調用K_STACK_DEFINE實現上面同樣的功能:

K_STACK_DEFINE(my_stack, MAX_ITEMS);

2.2 入棧

可以調用k_stack_push()函數,添加一個數據項到stack。

下面的示例展示,定義一個數據結構內存池,並且將他們的地址加入到stack中:

/* define array of data structures */
struct my_buffer_type {
    int field1;
    ...
    };
struct my_buffer_type my_buffers[MAX_ITEMS];

/* save address of each data structure in a stack */
for (int i = 0; i < MAX_ITEMS; i++) {
    k_stack_push(&my_stack, (stack_data_t)&my_buffers[i]);
}

2.3 出棧

可以調用k_stack_pop()函數,將數據項從stack中取出:

下面的示例展示了,一個線程動態的分配一個沒有使用的數據結構,當這個數據結構不在被需要,這個線程應該將這個數據結構的地址重新入棧:

struct my_buffer_type *new_buffer;

k_stack_pop(&buffer_stack, (stack_data_t *)&new_buffer, K_FOREVER);
new_buffer->field1 = ...

3 參考鏈接

https://docs.zephyrproject.org/latest/reference/kernel/data_passing/stacks.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章