Linux驱动学习记录-8.Linux并发与竞争
2021/10/16 7:14:44
本文主要是介绍Linux驱动学习记录-8.Linux并发与竞争,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Linux是多任务操作系统,存在福哦个任务操作同一设备或内存的情况,现在介绍并发的管理。
文章目录
- 一、原子操作
- 1.整形操作API函数
- 2.原子位操作API函数
- 二、自旋锁
- 1.自旋锁
- 2.API函数
- 3.其他类型的锁
- 三、信号量
- 1.信号量简介
- 2.API函数
- 三、互斥体
- 1.互斥体简介
- 2.API函数
一、原子操作
1.整形操作API函数
Linux内核定义了atomic_t的结构体来完成整形数据的原子操作。用原子变量代替整形变量。
typedef struct { int counter; }atomic_t; atomic_t a; atomic_t b = ATOMIC_INIT(0);
函数 | 描述 |
---|---|
ATONMIC_INT(int i) | 定义原子变量并初始化值为i |
int atomic_read(atomic_t *v) | 读取v的值,并且返回 |
void atomic_set(atomic_t *v, int i) | 向v写入i |
void atomic_add(int i, atomic_t *v) | v加上i |
void atomic_sub(int i, atomic_t *v) | v减去i |
void atomic_inc(atomic_t *v) | v自加1 |
void atomic_dec(atomci_t *v) | v自减1 |
int atomic_dec_return(atomic_t *v) | v自建1,并返回v的值 |
int atomic_inc_return(atomic_t *v) | v自加1,并返回v的值 |
int atomic_sub_and_test(int i, atomic_t *v) | v减去i,为0返回真,否则返回假 |
int atomic_dec_and_test(atomic_t *v) | v自减1,为0返回真,否则返回假 |
int atomic_inc_and_test(atomic *v) | v自加1,为0返回真,否则返回假 |
int atomic_add_negative(int i, atomic_t *v) | v加上i,为负返回真,否则返回假 |
2.原子位操作API函数
函数 | 描述 |
---|---|
void set_bit(int nr,void *p) | 将地址p的第nr位设置1 |
void clesr_bit(int nr, void *p) | 将地址p的第nr位清零 |
void change_bit(int nr, void *p) | 将地址p的第nr位翻转 |
int test_bit (int nr, void *p) | 获取地址p的第nr位 |
int test_and_set_bit(int nr, void *p) | 获取地址p的nr位,再置1 |
int test_and_clesr_bit(int nr, void *p) | 获取地址p的nr位,再清零 |
int test_and_change_bit(int nr, void *p) | 获取地址p的nr位,再翻转 |
二、自旋锁
1.自旋锁
原子操作只能对整形或者位保护,自旋锁可以保护临界区,等待自旋锁的进程会一直出于自旋状态,会浪费处理器时间,降低系统性能,所以自旋锁适用于短时期轻量级加锁。
typedef struct spinlock { /**/ } spinlock_t; spinlock_t lock;
2.API函数
函数 | 描述 |
---|---|
DEFINE_SPINLOCK(spinlock_t lock) | 定义并初始化一个自选变量 |
int spin_lock_init(spinlock_t *lock) | 初始化自旋锁 |
void spin_lock(spinlock_t *lock) | 加锁 |
void spin_unlock(spinlock_t *lock) | 解锁 |
int spin_trylock(spinlock_t *lock) | 尝试获取指定自旋锁,没获取返回0 |
int soin_is_locked(spinlock_t *lock) | 检查自旋锁是否被获取,没获取返回非0,获取返回0 |
被自旋锁保护的临界区不能调用能够引起睡眠或阻塞的API函数,否则会产生死锁现象。获取锁之前要禁止本地中断。
spin_lock(&lock); /* 临界区,程序尽量精简 */ spin_unlock(&lock);
函数 | 描述 |
---|---|
void spin_lock_irq(spinlock_t *lock) | 禁止本地中断,获取自旋锁 |
void spin_unlock_irq(spinlock_t *lock) | 激活本地中断,释放自旋锁 |
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags) | 保存中断状态,禁止本地中断,获取自旋锁 |
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) | 中断恢复以前状态,激活本地中断,释放自旋锁 |
在线程中建议使用后面两个,保存/恢复中断状态。在中断中使用spin_lock/spin_unlock
3.其他类型的锁
读写自旋锁,一个表里的数据进行保护,每次只能一个操作,读或者写。
typedef struct{ arch_rwlock_t raw_lock; }rwlock_t;
顺序锁,允许在写的时候读,但不允许同时并发的写操作。
typedef struct { struct seqcount seqcount; spinlock_t lock; } seqlock_t;
三、信号量
1.信号量简介
相比于自旋锁,信号量让进程进入休眠状态,不再占用cpu资源。而自旋锁让进程自旋。信号量适用于占用资源较长的场景。信号量不能用于中断,因为信号量引起休眠,中断不能休眠。如果临界区较短,不适用信号量,因为休眠和唤醒也要开销,不划算。
信号量有一个信号量值,初始化是如果大于1,就是计数型信号量,没访问一次信号量减一,直到等于0,不再访问,等待其他进程释放信号量,加一。如果信号量值不大于1,就是互斥访问,此时就是二值信号量。
struct semaphore { raw_spinlock_t lock; unsigned int count; struct list_head wait_list; }
2.API函数
函数 | 描述 |
---|---|
DEFINE_SEAMPHORE(name) | 定义一个信号量,设值为1 |
void sema_init(struct semaphore *sem, int val) | 初始化信号量,设值为val |
void down(struct semaphore *sem) | 获取信号量,休眠 |
int down_trylock(struct semaphore *sem) | 尝试获取信号量,获取就返回0,没获取返回非0 |
int down_interruptible(struct semaphore *sem) | 此函数进入休眠可以被信号打断 |
void up(struct semaphore *sem) | 释放信号量 |
三、互斥体
1.互斥体简介
互斥体访问表示一次只有一个线程可以访问共享资源,可以让信号量的值为1,也可代表互斥访问。Linux提供互斥体-mutex。互斥访问建议使用mutex,而不用信号量。
struct mutex{ atomic_t count; spinlock_t wait_lock; }
mutex可以导致休眠,不能在中断中使用互斥体,中断只能使用自旋锁
和信号量一样,mutex保护的临界区可以调用引起阻塞的函数
必须由mutex持有者释放,并且mutex不能递归上锁和解锁
2.API函数
函数 | 描述 |
---|---|
DEFINE_MUTEX(name) | 定义并初始化mutex |
void mutex_init(struct mutex *lock) | 初始化mutex |
void mutex_lock(struct mutex *lock) | 获取mutex,获取失败就休眠 |
void mutex_unlock(struct mutex *lock) | 释放mutex |
int mutex_trylock(struct mutex *lock) | 尝试获取mutex,成功返回1,失败返回0 |
int mutex_is_locked(struct mutex *lock) | 判断mutex是否被获取,是返回1,否返回0 |
int mutex_lock_interruptible(struct mutex *lock) | 获取信号量失败进入休眠,可以被信号打断 |
这篇关于Linux驱动学习记录-8.Linux并发与竞争的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法