简图记录-linux内核同步基础

一、概念

同步:为了达到多线程协同目的而设计的机制,通常包含异步通信机制和互斥机制;

常见并发原因:中断发送,软中断/tasklet,内核抢占,睡眠以及用户空间同步,多核处理器发生的多对称处理;

用户抢占 与 内核抢占 :用户抢占指当 内核从系统调用 或者 中断中返回用户空间时,当need_resched置位,会调用shedule调用;内核抢占 指 2.6 及以后的内核的特性,当更高优先级的任务出现,可以挂起当前正在内核态运行的低优先级进程;

二、典型同步方法

信号量:能导致睡眠的计数锁,count > 0 可获取【可长期锁定】

sema_init(struct semaphore *sem, int val) //初始化信号量,将信号量计数器值设置val。
down(struct semaphore *sem) // 获取信号量(不可被中断)。
down_interruptible(struct semaphore *sem) //可被中断地获取信号量,如果被信号中断返回错误。
up(struct semaphore *sem) //释放信号量sem。

互斥体:计数器为1的信号量(简化版)【可长期锁定】

mutex_init(struct mutex *lock) // 初始化锁
mutex_lock(struct mutex *lock)	// 加锁,如果不可用则睡眠
mutex_unlock(struct mutex *lock) // 解锁

自旋锁:只能被一个可执行任务持有的锁,否则忙等【低开锁加锁开销,短期锁定,不可休眠】

spin_lock_init(&lock); // 初始化锁

spin_lock(&lock);//获取自旋锁
spin_lock_irq(&lock);//关中断,获取自旋锁,不建议使用
spin_lock_irqsave(&lock, flags);//关中断,保存中断状态,获取自旋锁

spin_unlock(&lock);//解锁
spin_unlock_irq(&lock);// 解锁,并打开中断(不建议使用)
spin_unlock_irqrestore(&lock, flags); // 解锁,并用flags恢复中断状态

原则操作:提供对整数和位操作的一组不能被分割指令执行的操作【性能最优,使用受限】

ATOMIC_INIT(int i) // 声明一个atomic_t变量初始化为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(atomic_t *v) // 原子地给v减1

void set_bit(int nr, void *addr) // 原子地设置addr所指对象的第nr位
void clear_bit(int nr, void *addr) //原子地清空addr所指对象的第nr位
void change_bit(int nr, void *addr) // 原子地翻转addr所指对象的第nr位

等待队列:以队列为基础,与进程调度结合紧密,实现异步事件通知处理机制。

init_waitqueue_head(wait_queue_head_t *queue); //动态初始化等待队列
DECLARE_WAIT_QUEUE_HEAD(queue);// 静态定义并初始化等待队列

wait_event(queue, condition);
 // 不可打断的在等待队列睡眠,直到唤醒时condition为真
wait_event_interruptible(queue, condition); 
// 睡眠直到唤醒时condition为真返回0 或 被信号唤醒返回-ERESTARTSYS
wait_event_timeout(queue, condition, timeout);
 // 指定timeout时间睡眠,若唤醒condition为真 返回剩余时间,若timeout返回0
wait_event_interruptible_timeout(queue, condition, timeout);
 // 若唤醒condition为真 返回剩余时间),timeout返回0,信号唤醒返回-ERESTARTSYS

void wake_up(wait_queue_head_t *queue); // 唤醒
void wake_up_interruptible(wait_queue_head_t *queue); // 唤醒(只针对可信号打断的)

三、常见同步问题

锁、信号量、mutex、等待队列 没有初始化就开始使用;

AA死锁(连续请求同一把锁),或者 ABBA 死锁 (一个进程持有A请求B,一个进程持有B请求A)

wait_event_interruptible_timeout 返回值没有正确判断,注意3种返回值:若唤醒condition为真 返回剩余时间),timeout返回0,信号唤醒返回-ERESTARTSYS;

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值