linux内核互斥与同步

     本文将按照自己之前根据《深入Linux设备驱动程序内核机制》对linux内核互斥与同步的学习和理解,将自己当时所做的笔记写到此blog上。其中有的图片会是从《深入Linux设备驱动程序内核机制》中截取的。

1. 自旋锁

    spinlock_t结构体的定义:

typedef struct spinlock {
	union {
		struct raw_spinlock rlock;//这个是和体系结构相关的实现

#ifdef CONFIG_DEBUG_LOCK_ALLOC
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
		struct {
			u8 __padding[LOCK_PADSIZE];
			struct lockdep_map dep_map;
		};
#endif
	};
} spinlock_t;

    spin_lock()的原理就是通过不断循环查询spinlok_t.raw_spinlock.arch_spinlock_t.init来实现原地自旋。

常用的变体有:

spinlock图片1

上图来源于《深入Linux设备驱动程序内核机制》。

    preempt_disable():"preempt_count+1"操作,禁止内核抢占

    local_irq_disable():禁止cpu响应中断

    local_irq_save(flags):禁止cpu响应中断,并保存FLAGS寄存器

    local_bh_disable():禁止软中断

ps:内核抢占发生的时机:1. 中断处理程序返回内核空间之前 2. 内核中显式调用schedule()函数 3. 内核执行中被阻塞(此时也会调用schedule(),和2类似)

用户抢占发生的时机:1. 中断处理程序返回用户空间时 2. 系统调用返回用户控件时

2. 读写锁

    rwlock的特点:1. 如果当前有进程正在写,那么其他进程就不能读,当然也不能写 2. 如果当前有进程正在读,那么其他进程可以读,但是不能写。

   相对于spinlock的多个版本,rwlock同样有多个版本。

   对于读取者:

        void read_lock(rwlock_t *lock);

        void read_lock_irq(rwlock_t *lock);

        void read_lock_irqsave(rwlock_t *lock, unsigned long flags);

        void read_unlock(rwlock_t *lock);

        void read_unlock_irq(rwlock_t *lock);

        void read_unlock_irqsave(rwlock_t *lock, unsigned long flags);

    对于写入者:

        void write_lock(rwlock_t *lock);

        void write_lock_irq(rwlock_t *lock);

        void write_lock_irqsave(rwlock_t *lock, unsigned long flags);

        void write_unlock(rwlock_t *lock);

        void write_unlock_irq(rwlock_t *lock);

        void write_unlock_irqsave(rwlock_t *lock, unsigned long flags);

    try版本:

        int read_lock(rwlock_t *lock);

        int write_lock(rwlock_t *lock);

3.信号量

    初始化信号量:

sema_init

获取信号量:

sem_down

释放信号量:

 

4. 小总结

    spin_lock:通过不断循环查询spin_lock_t.raw_spinlock_t.arch_spinlock_t.int来实现原地自旋。

    semaphore:通过等待链表(类似等待队列)实现任务的挂起来等待信号量。将当前不能获取该信号量的任务添加到该等待链表sem->wait_list(类似等待队列)上进行等待,有down()获取/等待以及up()释放/唤醒两种操作,不能获取semaphore的任务将会挂起等待,因此会有schedule()发生。通过sem->lock实现sem的互斥访问。

    等待队列:通过wait_event()会建立一个wait_queue_t结构体,并将current进程放到该结构体中,将该结构体添加到wait_queue_head_t的链表上,将current任务状态设置为TASK_UNINTERRUPTIBLE,即挂起当前任务通过wake_up()唤起等待队列上的任务。重点在于等待某个时间发生,将任务挂起或者唤醒。

    工作队列:中断的下半部机制,通过sechedule_work()将一个任务添加到系统的工作队列(也可以是自己创建的工作队列),然后唤醒系统的worker工作线程来处理工作队列中的任务。重点在于将工作任务交给系统线程来执行。

    工作队列和等待队列将会在下一次介绍。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值