linux中信号量和互斥

时间:2022-07-05 15:17:12

信号量及互斥很多时候是为了解决对于共享资源的访问而导致异常而产生的,当我们使用的内核代码使用了譬如全局变量,静态变量,等等非局部变量的都会或多或少的导致计算异常或者是程序异常。我们除了倡导少用这些个变量来完成同样的任务,还需要在有时候不得不使用的这些变量时,学会利用信号量以及互斥的原理来避免对这些变量的异常访问。

信号量其实就是一个计数的,当资源在访问时,将其减1,当资源释放时,将其加1,,当信号量的这个计数小于1时,认为资源不可用,堵塞进程,或者堵塞进程一段时间后返回。

其实互斥也是一种特殊的信号量,当信号量就只有在1和0之间来回切换时,其实就可以理解为互斥了,因为假如我在使用一个东西时,别人不可以用,当我用完了,别人才可以用。

因为linux版本的原因,可能以下说的可能会有所不同。

Semaphore.h (common\include\linux)中定义了关于信号量的初始化以及使用, 有 2种方法来使用这些信号量。

@1:DEFINE_SEMAPHORE(name)//name 是我们使用信号量的名字 ,默认的信号量初始化为1了,表示资源同时只能有一个进程能使用

#define DEFINE_SEMAPHORE(name)	\
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
#define __SEMAPHORE_INITIALIZER(name, n)				\{									\	.lock		= __RAW_SPIN_LOCK_UNLOCKED((name).lock),	\	.count		= n,						\	.wait_list	= LIST_HEAD_INIT((name).wait_list),		\}

@2:动态初始化

static inline void sema_init(struct semaphore *sem, int val)

static inline void sema_init(struct semaphore *sem, int val)
{
static struct lock_class_key __key;
*sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
}
这个函数是可以程序运行中可以调用的函数,区别于@1,是可以认为的可以初始化val,以及运行时分配。

初始化了信号量,还需要对共享资源进行上锁。下面的函数的几个版本

extern void down(struct semaphore *sem);
extern int __must_check down_interruptible(struct semaphore *sem);
extern int __must_check down_killable(struct semaphore *sem);
extern int __must_check down_trylock(struct semaphore *sem);
extern int __must_check down_timeout(struct semaphore *sem, long jiffies);

函数定义 功能说明
sema_init(struct semaphore *sem, int val) 初始化信号量,将信号量计数器值设置val。
down(struct semaphore *sem) 获取信号量,不建议使用此函数。
down_interruptible(struct semaphore *sem) 可被中断地获取信号量,如果睡眠被信号中断,返回错误-EINTR。
down_killable (struct semaphore *sem) 可被杀死地获取信号量。如果睡眠被致命信号中断,返回错误-EINTR。
down_trylock(struct semaphore *sem) 尝试原子地获取信号量,如果成功获取,返回0,不能获取,返回1。
down_timeout(struct semaphore *sem, long jiffies) 在指定的时间jiffies内获取信号量,若超时未获取,返回错误-ETIME。
up(struct semaphore *sem) 释放信号量sem。
 
看完上边的表格应该就清楚了,一般较多的使用的是

extern int __must_check down_interruptible(struct semaphore *sem);

extern int __must_check down_trylock(struct semaphore *sem);

extern void up(struct semaphore *sem);

 互斥锁是特殊的信号量,其计数只有在0和1之间徘徊,那就是可用或者不可用。

有两种方式可以初始化互斥锁,其主要头文件在Mutex.h (include\linux)

1:编译时确定

#define DEFINE_MUTEX(mutexname) \
struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
2.运行时确定

# define mutex_init(mutex) \
do { \
static struct lock_class_key __key; \
\
__mutex_init((mutex), #mutex, &__key); \
} while (0)

其使用方法一般如下

1.

mutex_init(mutex) 
2.
mutex_lock_interruptible(struct mutex *lock) 可中断的
或者是
mutex_lock(struct mutex *lock)
3.执行完任务后

mutex_unlock