ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux驱动学习记录-8.Linux并发与竞争

2021-10-15 19:03:05  阅读:147  来源: 互联网

标签:struct int lock 信号量 并发 mutex atomic Linux 驱动


Linux是多任务操作系统,存在福哦个任务操作同一设备或内存的情况,现在介绍并发的管理。


文章目录


一、原子操作

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)获取信号量失败进入休眠,可以被信号打断

标签:struct,int,lock,信号量,并发,mutex,atomic,Linux,驱动
来源: https://blog.csdn.net/weixin_41903358/article/details/120784210

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有