第九章 内核同步方法

  1. 原子操作
    1. 原子操作可以保证指令以原子的方式执行--执行过程不被打断
    2. 针对整数的原子操作只能对atomic_t类型的数据进行处理。引入特殊数据类型的原因:
      1. 让原子函数只接受atomic_t类型的参数,确保原子操作只与这种特殊类型数据一起使用
      2. 保证该类型不会被传递给其他任何非原子函数
      3. 确保编译器不对相应的值进行访问优化
      4. 不同体系结构上实现原子操作时,使用atomic_t可以屏蔽其间的差异
      5. 使用atomic_t的代码只能将该类型的数据当做24位来用。原因是SPARC体系结构上,对原子操作缺乏指令级的支持,是通过32位int类型的低8位中嵌入了一个锁来实现。但这一限制已经不存在了。
    3. 原子整数操作列表,声明在<asm/atomic.h>中  
      原子整数操作列表
      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减i
      int atomic_sub_and_test(int i, atomic *v)原子地给v减i,如果结果等于0返回真;否则返回假
      int atomic_add_and_test(int i, atomic *v)原子地给v加i,如果结果是负数返回真;否则返回假
      int atomic_dec_and_test(atomic_t *v)原子地给v减1,如果结果是0返回真;否则返回假
      int atomic_inc_and_test(atomic_t *v)原子地给v加1,如果结果是0返回真;否则返回假
    4. 对位这一级数据进行原子操作,声明在<asm/bitops.h>中
      原子位操作列表
      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位
      int test_and_set_bit(int nr, void *addr)原子地设置addr所指对象的第nr位,并返回原先的值
      int test_and_clear_bit(int nr, void *addr)原子地清空addr所指对象的第nr位,并返回原先的值
      int test_and_change_bit(int nr, void *addr)原子地翻转addr所指对象的第nr位,并返回原先的值
      int test_bit(int nr, void *addr)原子地返回addr所指对象的第nr位
    5. 内核还提供了一组非原子位操作,操作相同,不保证原子性,接口的名字是响应接口名字前缀多两个下划线
    6. 从指定地址开始搜索第一个被设置(或未被设置)的位:
      1. int find_first_bit(unsigned log *addr, unsigned int size)
      2. int find_first_zero_bit(unsigned log *addr, unsigned int size)
  2. 自旋锁
    1. 类型:spinlock_t  lock;
    2. 与体系接口相关的代码定义在<asm/spinlock.h>中,实际需要用到的接口定义在<linux/spinlock.h>中
      自旋锁方法列表
      spin_lock()获取指定的自旋锁
      spin_lock_irq()禁止本地中断并获取指定的锁
      spin_lock_irqsave()保存本地中断的当前状态,禁止本地中断,并获取指定的锁
      spin_unlock()释放指定的锁
      spin_unlock_irq()释放指定的锁,并激活本地中断
      spin_unlock_irqrestore()释放指定的锁,并让本地中断恢复到以前状态
      spin_lock_init()动态初始化指定的spinlock_t
      spin_trylock()试图获取指定的锁;如果未获取,则返回非0
      spin_is_locked()如果指定的锁正在被获取,则返回非0,否则返回0
  3. 读写自旋锁 
    1. 类型:rwlock_t lock;
      read_lock()

      获得指定的读锁

      read_lock_irq()禁止本地中断并获取指定读锁
      read_lock_irqsave()存储本地中断的当前状态,禁止本地中断并获取指定读锁
      read_unlock()释放指定的读锁
      read_unlock_irq()释放指定的读锁并激活本地中断
      read_unlock_irqsave()释放指定的读锁并将本地中断恢复到指定的前状态
      write_lock()

      获得指定的写锁

      write_lock_irq()禁止本地中断并获取指定写锁
      write_lock_irqsave()存储本地中断的当前状态,禁止本地中断并获取指定写锁
      write_unlock()释放指定的写锁
      write_unlock_irq()释放指定的写锁并激活本地中断
      write_unlock_irqsave()释放指定的写锁并将本地中断恢复到指定的前状态
      write_trylock()试图获得指定的写锁,如果写锁不可用则返回非0值
      rw_lock_init()初始化指定的rwlock_t
      rw_is_locked()如果指定的锁当前已被持有则返回非0值,否则返回0
  4. 信号量

    1. 是一种睡眠锁
    2. 类型:struct semaphore;
  5. 读写信号量
    1. 是互斥信号量
    2. 类型:struct rw_semaphore;
  6. 自旋锁和信号量的比较
  7. 完成变量
    1. 与信号量思想类似
  8. BKL
    1. BKL(大内核锁)是一个全局自旋锁
    2. 持有BKL的任务仍然可以睡眠。睡眠不会造成任务死锁,但是是不安全的
    3. 是递归锁,一个进程可以多次请求一个锁,并不会像自旋锁产生死锁现象
    4. 可以用在进程上下文
    5. BKL是有害的
  9. 内核抢占
  10. 顺序和屏障
    1. 编译器和处理器可能为了提高效率,对读写内存的指令重新排序
    2. 处理器提供机器指令来确保顺序要求,这些指令称做屏障
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值