目錄
本學筆記基於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