其他分享
首页 > 其他分享> > SylixOS同步互斥之二进制信号量(二)

SylixOS同步互斥之二进制信号量(二)

作者:互联网

1. 基本作用

上一章节我们介绍了互斥锁,用于“共享资源”的互斥访问,在驱动开发中我们有时候需要等待某种资源准备好之后才能继续执行代码,这就需要使用同步机制来实现这个目的。比如某个应用想要读取AD转换数据,但是这时候转换还未完成,那么就有两种基本处理方法:一是轮询某个寄存器直到AD转换完成;二是将当前线程阻塞,等待AD转换完成后在中断处理中唤醒。第一种方法由于一直在轮询寄存器,cpu的占用率比较高,其他线程得不到运行,cpu利用率较低;第二种方法由于线程阻塞住之后系统可以调度其他的线程运行,cpu利用率较高,但是需要系统提供相应的同步机制。

多个线程可以等待同一个二进制信号量,唤醒的时候根据实际需要可以唤醒优先级最高的线程或者唤醒所有阻塞的线程。二进制信号量详细使用方法在《SylixOS应用开发手册》的7.3.1章节有介绍,这里只介绍基本用法和使用过程中的一些注意事项或者比较重要的东西。

2. 二进制信号量相关接口

2.1 创建二进制信号量

类似于互斥锁,二进制信号量在使用之前也需要先进行创建,这是通过API_SemaphoreBCreate 接口实现的,如下所示。

LW_API LW_OBJECT_HANDLE API_SemaphoreBCreate(CPCHAR             pcName,
                                             BOOL               bInitValue,
                                             ULONG              ulOption,
                                             LW_OBJECT_ID      *pulId); /*  建立二进制信号量            */

成功返回二进制信号量句柄,失败返回错误码。

2.2 阻塞等待二进制信号量

当资源没有准备好时,一般情况下需要将当前线程阻塞住来等待别的线程或者中断来唤醒,这是通过API_SemaphoreBPend 接口来实现的,如下所示。

LW_API ULONG            API_SemaphoreBPend(LW_OBJECT_HANDLE  ulId, 
                                           ULONG             ulTimeout);/*  等待二进制信号量            */

成功返回0,失败返回错误码,比如等待超时会返回ERROR_THREAD_WAIT_TIMEOUT。调用此接口时会将二进制信号量的值减去1,如果减之前值已经是0的话,就会将当前线程阻塞住,这也是为啥我们在初始化的时候需要将二进制信号量初始值设置为0的原因,因为只有这样设置调用此接口的线程才能真正的阻塞住。

2.3 唤醒二进制信号量

当资源准备好之后,就可以唤醒通知阻塞在二进制信号量上的线程,表示资源已经准备好了,快来使用。根据唤醒的需求不同,可以分为唤醒优先级最高的线程和全部唤醒两种方式,下面分别作介绍。

2.3.1 唤醒单个线程

如果只需要唤醒所有阻塞线程中优先级最高的那个线程的话,则可以使用API_SemaphoreBPost 来实现,如下所示。

LW_API ULONG            API_SemaphoreBPost(LW_OBJECT_HANDLE  ulId);     /*  RT 释放信号量               */

成功返回0,失败返回错误码。如果没有线程阻塞在此二进制信号量上时,调用此接口会将二进制信号量的值恢复为1。

2.3.2 唤醒全部线程

如果需要将阻塞在二进制信号量上的所有线程都唤醒的话,可以使用API_SemaphoreBFlush 接口来实现,如下所示。

LW_API ULONG            API_SemaphoreBFlush(LW_OBJECT_HANDLE  ulId, 
                                            ULONG            *pulThreadUnblockNum);
                                                                        /*  解锁所有等待线程            */

成功返回0,失败返回错误码。

2.4 销毁二进制信号量

当二进制信号量使用完毕之后,需要进行销毁以回收资源,这是通过API_SemaphoreBDelete 接口实现的,如下所示。

LW_API ULONG            API_SemaphoreBDelete(LW_OBJECT_HANDLE  *pulId); /*  删除二进制信号量            */

成功返回0,失败返回错误码。

3. 接口使用示例

这里用伪代码来说明上述接口的基本使用方法,详细的使用请参考应用开发手册。

LW_OBJECT_HANDLE sync_handle;

1. 创建二进制信号量,并将初始值设置为0,表示用作同步
sync_handle= API_SemaphoreBCreate("sync",
                                  LW_FALSE,
                                  LW_OPTION_WAIT_FIFO | LW_OPTION_OBJECT_GLOBAL,
                                  LW_NULL);

2. 当资源未准备好时,阻塞等待二进制信号量
API_SemaphoreBPend(sync_handle, LW_OPTION_WAIT_INFINITE);

3. 当资源准备好后,唤醒等待二进制信号量的线程
API_SemaphoreBPost(sync_handle);
或者
API_SemaphoreBFlush(sync_handle, NULL);

4. 使用完毕后,销毁二进制信号量
API_SemaphoreBDelete(&sync_handle);

关于二进制信号量还有其他一些接口,具体可以参见内核源码SylixOS/kernel/include/k_api.h。

4. 注意事项

标签:SylixOS,LW,二进制,信号量,互斥,API,线程,唤醒
来源: https://blog.csdn.net/li5830/article/details/122858381