概述
原子操作是指在执行的过程中不会被别的代码路径所中断的操作。
1.整型原子操作
1.1 设置源自变量的值
void atomic_set(atomic_t *v,int i); //设置原子变量的的值为i
atomic_t v = ATOMIC_INIT(0); //定义原子变量,并将其初始化为0
1.2 获取元原子变量的值
atomic_read(atomic_t *v); //返回原子变量的值
这是一个宏定义:#define atomic_read(v) (*(volatile int)&(v)->counter)
1.3 原子变量加减
void atomic_add(int i,atomic_t *v); //原子变量增加i
void atomic_sub(int i,atomic_t *v); //原子变量减少i
1.4 原子变量自增、自减
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
1.5 操作并测试
int atomic_int_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。
1.6 操作并返回
int atomic_add_and_return(int i,atomic_t *v);
int atomic_sub_and_return(int i,atomic_t *v);
int atomic_dec_and_return(atomic_t *v);
int atomic_inc_and_return(atomic_t *v);
以上操作后返回新的值。
2. 位原子操作
2.1 设置位
void set_bit(nr,void *addr); //设置addr地址的第nr位为1
2.2 清除位
void clear_bit(nr, void *addr); //设置addr地址的第nr位为0
2.3 改变位
void change_bit(nr, void *addr); //反置addr的第nr位
2.4 测试位
void test_bit(nr,void *addr); //返回addr的nr位
2.5 测试并操作位
void test_and_set_bit(nr, void *addr);
void test_and_clear_bit(nr,void *addr);
void test_and_change_bit(nr,void *addr);
3. 自旋锁
3.1 定义自旋锁
spinlock_t lock;
3.2 初始化自旋锁
spin_lock_init(&lock);
3.3 获得自旋锁
spin_lock(&lock);
spin_trylock(&lock);
3.4 释放自旋锁
spin_unlock(&lock);
还有一些自旋锁的扩展:
spin_lock_irq() = spin_lock() + local_irq_disable()
spin_unlock_irq() = sqin_unlock() + lock_irq_enable()
...
4. 信号量的使用
信号量的使用方法和原子变量基本相同,不同的是当获取不到自旋锁时,进程不会原地打转 而是进入睡眠状态,他不会消耗cpu资源。
4.1 定义信号量
struct semaphore sem;
4.2 初始化信号量
void sema_init(&sem,int val);
#define init_MUTEX(sem ,1);
#define init_LOCKED(sem) sema_init(sem,0)
还有初始化信号量的简便方式:
DECLARE_MUTEX(name)
DECLARE_MUTEX_LOCKED(name)
4.3 获得信号量
void down(&sem); //他会导致睡眠,不能用于中断上下文,且不能被信号打断
int down_interruptable(&sem); //睡眠可以被信号打断
int down_trylock(&sem); //获得锁返回0,否则返回非0,可用于中断上下文
eg:
if (down_interruptable(&sem))
return -ERESTARTSYS;
4.4 释放信号量
void up(&sem);
5. 完成量
完成量是一种比用信号量更好的同步机制,它用于一个执行单元等待另一个执行单元执行完 某事。
5.1 定义完成量
struct completion cmp;
5.2 初始化完成量
init_completion(&cmp);
DECLARE_COMPLETION(cmp);
5.3 等待完成量
void wait_for_completion(&cmp);
5.4 唤醒完成量
void completion(&cmp);
void completion_all(&cmp);
6. 自旋锁和信号量的选用原则
1. 当需要持有锁时间较长时使用信号量较好,较短时使用自旋锁更佳。
2. 若临界区中包含可能引起阻塞的代码,最好用信号量。
3. 在被保护的资源需要在中断或软中断中使用的时候只能用自旋锁,或者sem_trylock();
7. 读写信号量
读写信号量是在信号量基础上的优化,它允许多读一写.
相关函数:
struct rw_semaphore sem;
void init_rwsem(&sem);
down_read(&sem);
down_read_trylock(&sem);
up_read(&sem);
void down_write(&sem);
int down_write_trylock(&sem);
up_write(&sem);
8. 互斥体
srtuct mutex m;
mutex_init(&m);
mutex_lock(&m);
mutex_lock_interruptable(&m);
mutex_trylock(&m);
mutex_unlock(&m);
4.3
转载于:https://blog.51cto.com/lijiajia/1106960
最后
以上就是无奈八宝粥为你收集整理的linux系统下的原子操作的全部内容,希望文章能够帮你解决linux系统下的原子操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复