栈¶
栈(stack) 是一个内核对象,它实现了传统的后进先出(last in first out)队列,允许线程和 ISR 添加大小为 32 比特的数据值。
概念¶
可以定义任意数量的栈。每个栈通过其内存地址进行引用。
栈的关键属性包括:
- 队列: 它包含了已被添加但还未被移除的长度为 32 比特的数据值。队列使用整型数组实现,且必须在 4 字节边界上对齐。
- 最大数量:栈的容量。
栈必须先初始化再使用。初始化时会将栈的队列设为空。
数据可以被线程或者 ISR 添加 到栈中。如果有线程在该栈上等待数据,则该数据直接被传递该线程;否则,该数据会被添加到栈的队列中。内核在添加数据到栈时,不会检测该栈的队列值是否已达到最大数量。
注解
向一个已满的栈添加数据会导致数组越界,最终会产生不可预料的行为。
数据项可以被线程从栈中 移除。如果该栈的队列为空,线程在这个栈上进行等待。多个线程可以同时在某个空栈上等待,当一个新的数据项被添加时,它会被给予优先级最高的、等待时间最久的线程。
注解
ISR 虽然也可以从栈中移除数据,但是如果栈为空,ISR 不能进行等待。
实现¶
定义栈¶
使用类型为 struct k_stack
的变量可以定义一个栈。栈定义后必须使用函数 k_stack_init()
对其进行初始化。
下面的代码定义并初始化了一个可以容纳 10 个值的空栈。
#define MAX_ITEMS 10
uint32_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);
压栈¶
函数 k_stack_push()
可用于将数据项压栈。
下面的代码基于上面的例程之上,它展示了线程是如何通过保存数据结构池的内存地址到栈中来创建数据结构池的过程。
/* 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, (uint32_t)&my_buffers[i]);
}