linux的信号量操作

1.在linux驱动层中有很多并发控制的机制,但是这里只介绍两个因为我感觉这两个就可以解决几乎所有问题

1.整形原子操作:
整型原子操作
1.设置原子变量的值
void atomic _ set(atomic _ t *v, int i); //设置原子变量的值为 i
atomic _ t v = ATOMIC _ INIT(0); //定义原子变量 v 并初始化为 0
2.获取原子变量的值
atomic _ read(atomic _ t *v); //返回原子变量的值
3.原子变量加/减
void atomic _ add(int i, atomic _ t *v); //原子变量增加 i
void atomic _ sub(int i, atomic _ t *v); //原子变量减少 i
4.原子变量自增/自减
void atomic _ inc(atomic _ t *v); //原子变量增加 1
void atomic _ dec(atomic _ t *v); //原子变量减少 1
5.操作并测试
int atomic _ inc _ and _ test(atomic _ t *v);
int atomic _ dec _ and _ test(atomic _ t *v);
int atomic _ sub _ and _ test(int i, atomic _ t *v);
上述操作对原子变量执行自增、自减和减操作后(注意没有加)测试其是否为 0,
为 0 则返回 true,否则返回 false。
6.操作并返回
int atomic _ add _ return(int i, atomic _ t *v);
int atomic _ sub _ return(int i, atomic _ t *v);
int atomic _ inc _ return(atomic _ t *v);
int atomic _ dec _ return(atomic _ t *v);
上述操作对原子变量进行加/减和自增/自减操作,并返回新的值。

位原子操作
1.设置位
void set _ bit(nr, void *addr);
上述操作设置 addr 地址的第 nr 位,所谓设置位即将位写为 1。
2.清除位
void clear _ bit(nr, void *addr);
上述操作清除 addr 地址的第 nr 位,所谓清除位即将位写为 0。
3.改变位
void change _ bit(nr, void *addr);
上述操作对 addr 地址的第 nr 位进行反置。
4.测试位
test _ bit(nr, void *addr);
上述操作返回 addr 地址的第 nr 位。
5.测试并操作位
int test _ and _ set _ bit(nr, void *addr);
int test _ and _ clear _ bit(nr, void *addr);
int test _ and _ change _ bit(nr, void *addr);
上述 test_and_xxx_bit (nr, void *addr)操作等同于执行 test_bit (nr, void *addr) 后
再执行 xxx_bit(nr, void *addr)。

Linux 系统中与自旋锁相关的操作主要有如下 4 种。
自旋锁只能被一个设备打开,如果另一个设备想要打开只能等待,锁被释放。
1.定义自旋锁
spinlock _ t spin;
2.初始化自旋锁
spin _ lock _ init(lock)
该宏用于动态初始化自旋锁 lock
3.获得自旋锁
spin _ lock(lock)
该宏用于获得自旋锁 lock,如果能够立即获得锁,它就马上返回,否则,它将自
旋在那里,直到该自旋锁的保持者释放;
spin _ trylock(lock)
该宏尝试获得自旋锁 lock,如果能立即获得锁,它获得锁并返回真,否则立即返回假,实际上不再“在原地打转”;
4.释放自旋锁
spin _ unlock(lock)
该宏释放自旋锁 lock,它与 spin_trylock 或 spin_lock 配对使用。

信号量的使用
信号量(semaphore)是用于保护临界区的一种常用方法,它的使用方式和自旋锁
类似。与自旋锁相同,只有得到信号量的进程才能执行临界区代码。但是,与自旋锁
不同的是,当获取不到信号量时,进程不会原地打转而是进入休眠等待状态。
Linux 系统中与信号量相关的操作主要有如下 4 种。
1.定义信号量
下列代码定义名称为 sem的信号量。
struct semaphore sem;
2.初始化信号量
void sema _ init (struct semaphore *sem, int val);
该函数初始化信号量,并设置信号量 sem 的值为 val。尽管信号量可以被初始化
为大于 1 的值从而成为一个计数信号量,但是它通常不被这样使用。
void init _ MUTEX(struct semaphore *sem);
该函数用于初始化一个用于互斥的信号量,它把信号量 sem 的值设置为 1,等同于
sema_init (struct semaphore *sem, 1)。
void init _ MUTEX _ LOCKED (struct semaphore *sem);
该函数也用于初始化一个信号量,但它把信号量 sem 的值设置为 0,等同于
sema_init (struct semaphore *sem, 0)。
此外,下面两个宏是定义并初始化信号量的“快捷方式”。
DECLARE _ MUTEX(name)
DECLARE _ MUTEX _ LOCKED(name)
前者定义一个名为 name 的信号量并初始化为 1,后者定义一个名为 name 的信号量
并初始化为 0。
3.获得信号量
void down(struct semaphore * sem);
该函数用于获得信号量 sem,它会导致睡眠,因此不能在中断上下文使用。
int down _ interruptible(struct semaphore * sem);
该函数功能与 down()类似,不同之处为,因为 down()而进入睡眠状态的进程不能
被信号打断,而因为 down_interruptible()而进入睡眠状态的进程能被信号打断,信号
也会导致该函数返回,这时候函数的返回值非 0。
int down _ trylock(struct semaphore * sem);
该函数尝试获得信号量 sem,如果能够立刻获得,它就获得该信号量并返回 0,
否则,返回非 0 值。它不会导致调用者睡眠,可以在中断上下文使用。
在使用 down_interruptible()获取信号量时,对返回值一般会进行检查,如果非 0,
通常立即返回-ERESTARTSYS,如:
if (down _ interruptible(&sem))
{
return - ERESTARTSYS;
}4.释放信号量
void up(struct semaphore * sem);
该函数释放信号量 sem,唤醒等待者。
信号量一般这样被使用,如下所示:
//定义信号量
DECLARE _ MUTEX(mount _ sem);
down(&mount _ sem);//获取信号量,保护临界区

critical section //临界区

up(&mount _ sem);//释放信号量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值