linux内核互斥与同步

来源:互联网 发布:游戏优化是看什么 编辑:程序博客网 时间:2024/06/12 23:14

     本文将按照自己之前根据《深入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
原创粉丝点击