Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9417980
  • 博文数量: 1748
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 20070
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1748)

文章存档

2024年(24)

2023年(26)

2022年(112)

2021年(217)

2020年(157)

2019年(192)

2018年(81)

2017年(78)

2016年(70)

2015年(52)

2014年(40)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: LINUX

2010-11-08 16:27:04

  1. 对并发的管理时系统移植和编程中的核心问题。
  2. 内核代码时抢占式的,你的驱动代码可能随时都有可能失去CPU时间片。
    设备中断也是导致并发执行的一种异步事件
    延迟代码执行的机制(workqueue,tasklet,定时器)也能造成并发。
    热插拔也是造成并发的事件
  3. PV信号灯    struct semaphore, 对所有调用者进行互斥。 不能用于中断处理函数中。
    1. void sema_init(struct semaphore *sem, int val); //val 为信号灯的初始值。
    2. 定义并初始化一个信号灯name
      DECLARE_MUTEX(name);  信号灯初始值为1
      DECLARE_MUTEX_LOCKED(name); 信号灯初始值为0
    3. 动态初始化
      void init_MUTEX(struct semaphore *sem);
      void init_MUTEX_LOCKED(struct semaphore *sem);
    4. PV 操作: P函数=down  V函数=up
      1. void down(struct semaphore *sem); //阻塞等待
      2. int down_interruptible(struct semaphore *sem); //阻塞可被中断(常用)
        他允许一个等待信号灯的用户空间进程被用户中断。正确使用down_interruptible需要一直检查它的返回值并且针对性的响应。若操作是可中断的, 函数返回非0,同时调用者将不再持有信号灯。
      3. int down_trylock(struct semaphore *sem);//非阻塞
      4. void up(struct semaphore *sem); //释放信号灯
      5. 读写信号灯 struct rw_semaphore,允许多个读任务并行。
        1. rwsem 必须在运行时显式的初始化 void init_rwsem(struct rw_semaphore *rwsem);
        2. void down_read(struct rw_semaphone *rwsem);
          void down_read_trylock(struct rw_semaphore *rwsem);
          void up_read(struct rw_semaphore *rwsem);
        3. void down_write(struct rw_semaphore *rwsem);
          int down_write_trylock(struct rw_semphore *sem);
          void up_write(struct rw_semaphore *sem);
          void downgrade_write(struct rw_semaphore *sem); //允许改变完之后其他读任务进入
        4. rwsem允许多个读任务并行持有信号灯。 写任务有优先权。 一般用于写操作较少并且占用时间较短的操作。
  4. completions 。 允许一个线程告诉另外一个线程工作已经完成。
    1. DECLARE_COMPLETION(my_completion);
    2. struct completion my_completion;
      init_completion(&my_completion);
    3. 等待completion
      void wait_for_completion(struct completion *c); //不可打断,若无人完成任务,则产生一个不可杀死的进程。
    4. 完成事件的发出
      void complete(struct completion *c); //唤醒一个等待的线程
      void complete_all(struct completion *c); //唤醒所有等待此完成事件的线程
    5. completion 是一个单发设备,使用一次就放弃。 如果没有使用completion_all,则重新使用一个completion结构时可以的。 如果使用了completion_all,那么重新使用前最好重新初始化 INIT_COMPLETION(struct completiomn c);来进行快速初始化
    6. completion 的机制的使用典型为 “模块退出和内核线程终止绑定”, 即部分驱动的工作是通过一个 while(1)的内核线程进行的, 当模块要退出时,__exit函数告诉内核线程退出并等待其结束。 内核提供函数给线程使用 complete_and_exit(struct completion *c, long retval);
  5. 自旋锁< linux/spinlock.h> spinlock_t 。比信号灯更常用的互斥机制。可用在不可睡眠的代码中(中断处理)
    1. 自旋锁有两个值: “上锁” “解锁”,获取锁是一个原子操作
    2. 初始化的两种方式
      静态:spinlock_t my_lock = SPIN_LOCK_UNLOCKED;
      动态:void spin_lock_init(spinlock_t *lock);
    3. 内核代码在持有自旋锁的时段,抢占在相关的处理器上被禁止,这样避免因抢占造成的资源竞争的情况。同时需要持有自旋锁的时间尽量短。
    4. 内核代码在持有自旋锁的时段应当避免睡眠,(copy_from_user, kmalloc,强行中断等),
      否则容易造成自旋死锁,一般情况下在持有自旋锁时禁止中断。有专门的自旋锁函数来禁用中断。
    5. 加锁
      void spin_lock(spinlock_t *lock);
      void spin_lock_irqsave(spinlock_t *lock, ulong flags);获得锁之前禁用本地中断,并把当前中断状态保存在flags变量中。
      void spin_lock_irq(spinlock_t *lock); 获得锁之前禁用本地中断,但不保存之前的中断状态
      void spin_lock_bh(spinlock_t *lock);获得锁之前禁用本地软中断, 但保留硬中断。
    6. 如果在中断子程序中获取自旋锁,必须使用spin_lock形式禁止中断,其他方式可能死锁。
      如果区分在只在软中断子程序中才获取自旋锁,而在硬件中断中没有对所进行访问的话可以直接是使用spin_lock_bh来安全避免死锁,同时允许硬件中断被调用。
    7. 解锁
      void spin_unlock(spinlock_t *lock);
      void spin_unlock_irqrestore(spinlock_t *lock, ulong flags);
      void spin_unlock_irq(spinlock_t *lock);
      void spin_unlock_bh(spinlock_t *lock);
    8. 非阻塞. try版本没有禁止中断的功能。
      int spin_trylock(spinlock_t *lock);
      int spin_trylock_bh(spinlock_t *lock);  
    9. 读写自旋锁 rwlock_t
      1. rwlock_t my_rwlock = RW_LOCK_UNLOCKED;
        rwlock_t my_rwlock; rwlock_init(&my_rwlock);
      2. void read_lock(rwlock_t *lock);
        void read_lock_irqsave(rwlock_t *lock, unsigned long flags);
        void read_lock_irq(rwlock_t *lock);
        void read_lock_bh(rwlock_t *lock);

        void read_unlock(rwlock_t *lock);
        void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
        void read_unlock_irq(rwlock_t *lock);
      3. void write_lock(rwlock_t *lock);
        void write_lock_irqsave(rwlock_t *lock, unsigned long flags);
        void write_lock_irq(rwlock_t *lock);
        void write_lock_bh(rwlock_t *lock);
        int write_trylock(rwlock_t *lock);

        void write_unlock(rwlock_t *lock);
        void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
        void write_unlock_irq(rwlock_t *lock);
        void write_unlock_bh(rwlock_t *lock);

        void read_unlock_bh(rwlock_t *lock);
阅读(1565) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~