目录
互斥信号量
在介绍二进制信号量时,曾讨论到如果二进制信号量创建时设置参数 bInitValue 为TRUE,则可以用于互斥访问共享资源。实际上,SylixOS 的二进制信号量实现的互斥性是将一个变量初始化标记为 1,等待信号量(Wait)时将该变量减 1(此时等于 0),如果另一个线程再次等待该信号量将阻塞,直到该信号量被释放(变量加 1),这样就实现了共享资源的互斥访问。
如果系统中只有两个线程,上面的过程是没有问题的。但是一旦有多个线程介入,上面过程将出现以下问题:
一个高优先级的线程可能也要访问同一个共享资源(这是完全有可能的),此时只能阻塞等待,但是可能会有另一个中等优先级的线程将占有信号量的线程抢占。这个过程导致了高优先级线程很长时间得不到运行(这是 SylixOS 不允许出现的情况)。
以上过程出现的问题就是经典的优先级反转问题。
互斥信号量用于共享资源需要互斥访问的场合,可以理解为初始值为 TRUE 的带优先级天花板和优先级继承机制(意在解决优先级反转问题)的二进制信号量,只有拥有互斥信号量的线程才有权释放互斥信号量。
1、Creat
一个 SylixOS 互斥信号量必须要调用 Lw_SemaphoreM_Create 函数创建之后才能使用,如果创建成功,该函数将返回一个互斥信号量的句柄。
#include <SylixOS.h>
LW_HANDLE Lw_SemaphoreM_Create(CPCHAR pcName,
UINT8 ucCeilingPriority,
ULONG ulOption,
LW_OBJECT_ID *pulId);
函数 Lw_SemaphoreM_Create 原型分析:
- 此函数成功返回互斥信号量的句柄,失败返回 NULL 并设置错误号;
- 参数 pcName 是互斥信号量的名字;
- 参数 ucCeilingPriority 在使用优先级天花板算法时有效,此参数为天花板优先级;
- 参数 ulOption 是互斥信号量的创建选项;
- 输出参数 pulId 返回互斥信号量的句柄(同返回值),可以为 NULL。
创建选项包含了二进制信号的创建选项,此外还可以使用,如下表所示的互斥信号量特有的创建选项。
需要注意,LW_OPTION_INHERIT_PRIORITY 和 LW_OPTION_PRIORITY_CEILING只能二选一,同样 LW_OPTION_NORMAL 和 LW_OPTION_ERRORCHECK 及LW_OPTION_RECURSIVE 只能三选一。
2、Delete
一个不再使用的互斥信号量,可以调用以下函数将其删除。删除后的信号量系统自动回收其占用的系统资源(试图使用被删除的互斥信号量将出现未知的错误)
#include <SylixOS.h>
ULONG Lw_SemaphoreM_Delete(LW_HANDLE *pulId);
函数 Lw_SemaphoreM_Delete 原型分析:
- 此函数返回错误号;
- 参数 pulId 是互斥信号量的句柄。
3、Wait
线程如果需要等待一个互斥信号量,可以调用 Lw_SemaphoreM_Wait 函数。
#include <SylixOS.h>
ULONG Lw_SemaphoreM_Wait(LW_HANDLE ulId, ULONG ulTimeout);
函数 Lw_SemaphoreM_Wait 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 ulId 是互斥信号量的句柄;
- 参数 ulTimeout 是等待的超时时间,单位为时钟嘀嗒 Tick。
4、Post
#include <SylixOS.h> ULONG Lw_SemaphoreM_Post(LW_HANDLE ulId);
函数 Lw_SemaphoreM_Post 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 ulId 是互斥信号量的句柄。
需要注意的是,只有互斥信号量的拥有者才能释放该互斥信号量。
5、Statu
#include <SylixOS.h>
ULONG Lw_SemaphoreM_Status(LW_HANDLE ulId,
BOOL *pbValue,
ULONG *pulOption,
ULONG *pulThreadBlockNum);
ULONG Lw_SemaphoreM_StatusEx(LW_HANDLE ulId,
BOOL *pbValue,
ULONG *pulOption,
ULONG *pulThreadBlockNum,
LW_HANDLE *pulOwnerId);
以上两个函数原型分析:
- 函数成功返回 0,失败返回错误号;
- 参数 ulId 是互斥信号量的句柄;
- 输出参数 pbValue 用于接收互斥信号量当前的状态;
- 输出参数 pulOption 用于接收互斥信号量的创建选项;
- 输出参数 pulThreadBlockNum 用于接收当前阻塞在该互斥信号量的线程数。
- 输出参数 pulOwnerId 用于接收当前拥有该互斥信号量的线程的句柄。
#include <SylixOS.h>
ULONG Lw_SemaphoreM_GetName(LW_HANDLE ulId, PCHAR pcName);
函数 Lw_SemaphoreM_GetName 原型分析:
- 此函数成功返回 0,失败返回错误号;
- 参数 ulId 是互斥信号量的句柄;
- 输出参数 pcName 是互斥信号量的名字,pcName 应该指向一个大小为LW_CFG_OBJECT_NAME_SIZE 的字符数组。