信号量是实现传统计数信号量的内核对象。

概念

可以定义任意数量的信号量(仅受可用 RAM 的限制)。每个信号量都由其内存地址引用。
信号量具有以下关键属性:

  • 指示可以获取信号量的次数的计数。计数为零表示信号量不可用。
  • 指示信号量计数可以达到的最大值的限制。

必须先初始化信号量,然后才能使用它。其计数必须设置为小于或等于其限制的非负值。
信号量可以由线程或 ISR 给出。提供信号量会增加其计数,除非计数已等于限制。
信号量可以由线程获取。获取信号量会减少其计数,除非信号量不可用(即在零处)。当信号量不可用时,线程可以选择阻塞等待。任意数量的线程可以同时等待不可用的信号量。给出信号量时,它由等待时间最长的优先级最高的线程获取。

定义信号量

信号量是使用k_sem类型定义的变量。然后必须通过调用k_sem_init()对其进行初始化。
下面的代码定义一个信号量,然后通过将其计数设置为 0 并将其限制设置为 1 来将其配置为二进制信号量。

  1. struct k_sem my_sem;
  2. k_sem_init(&my_sem, 0, 1);

也可以通过调用K_SEM_DEFINE在编译时定义和初始化信号量。

  1. K_SEM_DEFINE(my_sem, 0, 1);

释放信号量

信号量是通过调用k_sem_give()释放信号量。

  1. void input_data_interrupt_handler(void *arg)
  2. {
  3. /* notify thread that data is available */
  4. k_sem_give(&my_sem);
  5. ...
  6. }

获取信号量

信号量是通过调用k_sem_take()来获取。

  1. void consumer_thread(void)
  2. {
  3. ...
  4. if (k_sem_take(&my_sem, K_MSEC(50)) != 0) {
  5. printk("Input data not available!");
  6. } else {
  7. /* fetch available data */
  8. ...
  9. }
  10. ...
  11. }