目录
二进制信号量
SylixOS 的二进制信号量实现的互斥性是将一个变量初始化标记为 1,等待信号量(Wait)时将该变量减 1(此时等于 0),如果另一个线程再次等待该信号量将阻塞,直到该信号量被释放(变量加 1),这样就实现了共享资源的互斥访问。
二进制信号量的基本操作函数在线程与线程之间、中断与线程之间的操作过程如下图所示。

1.creat
二进制信号量主要应用在以下场合:
- 有允许线程访问的一个资源,使用二进制信号量作为互斥手段,初始值为 TRUE;
- 线程或中断通知另一个线程某件事件发生,初始值为 FALSE。
#include <SylixOS.h>
LW_HANDLE Lw_SemaphoreB_Create(CPCHAR pcName,
BOOL bInitValue,
ULONG ulOption,
LW_OBJECT_ID *pulId);
函数 Lw_SemaphoreB_Create 原型分析:
- 此函数返回二进制信号量的句柄,失败时为 NULL 并设置错误号;
- 参数 pcName 是二进制信号量的名字;
- 参数 bInitValue 是二进制信号量的初始值(FALSE 或 TRUE);
- 参数 ulOption 是二进制信号量的创建选项如图 3 所示;
- 输出参数 pulId 用于返回二进制信号量的句柄(同返回值),可以为 NULL。
参数 bInitValue 的不同决定了二进制信号量的用途不同,当 bInitValue 的值为 TRUE 时可以用于共享资源的互斥访问,如图1 所示。当 bInitValue 的值为 FALSE 时可以用于多线程间的同步,如图 2 所示。


信号量的创建选项参数见图 3 所示。SylixOS 提供了两种信号量等待队列:优先级(LW_OPTION_WAIT_PRIORITY)和 FIFO(LW_OPTION_WAIT_FIFO)。优先级方式则根据线程的优先级从队列中取出符合条件的线 程运行;FIFO 方式则根据先入先出的原则从队列中取出符合条件的线程运行。
需要注意的是,LW_OPTION_WAIT_PRIORITY 和 LW_OPTION_WAIT_FIFO 只能二选一,同样LW_OPTION_OBJECT_GLOBAL 和 LW_OPTION_OBJECT_LOCAL也只能二选一。其中LW_OPTION_OBJECT_GLOBAL 代表一种全局对象,LW_OPTION_OBJECT_LOCAL 代表一种局部对象,当进程退出时不会释放全局对象资源(除非特殊,一般不使用 GLOBAL 对象)。

2.delete
不再需要的二进制信号量可以调用Lw_SemaphoreB_Delete函数将其删除,SylixOS 将回收其占用的内核资源(试图使用被删除的二进制信号量将出现未知的错误)。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Delete(LW_HANDLE *pulId)
函数 Lw_SemaphoreB_Delete 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 pulId 是二进制信号量的句柄。
3.wait
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Wait(LW_HANDLE ulId, ULONG ulTimeout);
ULONG Lw_SemaphoreB_TryWait(LW_HANDLE ulId);
以上函数原型分析:
- 函数成功返回 0,失败返回错误号;
- 参数 ulId 是二进制信号量的句柄;
- 参数 ulTimeout 是等待的超时时间,单位为时钟节拍 Tick。
参数 ulTimeout除了可以使用数字外还可以使用如图 4 所示的宏。SylixOS 为二进制信号量等待提供了一种超时机制,当等待的时间超时时立即返回并设置 errno 为 ERROR_THREAD_WAIT_TIMEOUT。

中断服务程序不能调用 Lw_SemaphoreB_Wait 函数来等待一个二进制信号量,因为该函数在二进制信号量值为 FALSE 时会阻塞当前执行的任务,而中断服务程序用来处理最紧急的事情,因此是不允许被阻塞的,否则其他线程将得不到调度的机会。
中断服务程序可以使用 Lw_SemaphoreB_TryWait 函数尝试等待二进制信号量,因为Lw_SemaphoreB_TryWait 函数在二进制信号量的值为 FALSE 时会立即返回,不会阻塞当前线程。
4.post
释放一个二进制信号量可以调用 Lw_SemaphoreB_Post、Lw_SemaphoreB_Post2 或者Lw_SemaphoreB_Release 函数。 Lw_SemaphoreB_Post2 函数返回时可以通过参数 pulId 返回被激活的线程句柄,如果参数 pulId 被置为 NULL 时行为与Lw_SemaphoreB_Post 相同。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Post(LW_HANDLE ulId);
函数 Lw_SemaphoreB_Post 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 ulId 是二进制信号量的句柄。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Post2(LW_HANDLE ulId, LW_HANDLE *pulId);
函数 Lw_SemaphoreB_Post 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 ulId 是二进制信号量的句柄;
- 参数 pulId 返回被激活的线程 ID。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Release(LW_HANDLE ulId, ULONG ulReleaseCounter, BOOL *pbPreviousValue);
函数 Lw_SemaphoreB_Release 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 ulId 是二进制信号量的句柄;
- 参数 ulReleaseCounter 是释放二进制信号量的次数;
- 输出参数 pbPreviousValue 用于接收原来的二进制信号量状态,可以为 NULL。
5.clear
调用 Lw_ SemaphoreB_Clear 函数将清除二进制信号量,这将使二进制信号量的初始值置为 FALSE。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Clear(LW_HANDLE ulId);
函数 Lw_SemaphoreB_Clear 原型分析:
- 此函数返回错误号;
- 参数 ulId 是二进制信号量的句柄。
调用 Lw_ SemaphoreB_Flush 函数将释放在指定信号量上等待的所有线程。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_Flush(LW_HANDLE ulId, ULONG *pulThreadUnblockNum);
函数 Lw_SemaphoreB_Flush 原型分析:
- 此函数返回错误号;
- 参数 ulId 是二进制信号量的句柄;
- 输出参数 pulThreadUnblockNum 用于接收被解除阻塞的线程数,可以为 NULL。
6.属性
#include <SylixOS.h> ULONG Lw_SemaphoreB_Status(LW_HANDLE ulId, BOOL *pbValue, ULONG *pulOption, ULONG *pulThreadBlockNum);
函数 Lw_SemaphoreB_Status 原型分析:
- 此函数返回错误号;
- 参数 ulId 是二进制信号量的句柄;
- 输出参数 pbValue 用于接收二进制信号量当前的值(FALSE 或 TRUE);
- 输出参数 pulOption 用于接收二进制信号量的创建选项;
- 输出参数 pulThreadBlockNum 用于接收当前阻塞在该二进制信号量的线程数。
#include <SylixOS.h>
ULONG Lw_SemaphoreB_GetName(LW_HANDLE ulId, PCHAR pcName)
函数 Lw_SemaphoreB_GetName 原型分析:
- 此函数返回错误号;
- 参数 ulId 是二进制信号量的句柄;
- 输出参数 pcName 是二进制信号量的名字,pcName 应该指向一个大小为LW_CFG_OBJECT_NAME_SIZE 的字符数组。