内核同步方法总结

Linux中内核同步方法总结如下:
1、原子整数操作:
 原子操作可以保证指令以原子的方式运行--执行过程不能被打断.原子操作把读取和改变变量的行为包含在一个单步中执行,从而避免了竞争.

       定义:atomix_t t;

       Atomic_t u = ATOMIC_INIT(0);

  操作函数定义在中,原子操作是内联函数.通过内嵌汇编指令来实现.
  Int atomic_read(atomic_t v)
  Void atomic_set(atomic_t *v,int i)
  Void atomic_add(int i,atomic_t *v)
  Void atomic_sub(int i,atomic_t *v);
  
  Void atomic_inc(atomic_t *v);
  Void atomic_dec(atomic_t *v);
  原子加减1

  Int atomic_sub_and_test(int i,atomic_t *v)
  原子地从v减i,如果等于0,返回真,否则返回假.

  Int atomic_add_negative(int i,atomic_t *v)
  结果为负数返回真,否则返回假.
  
  Int atomic_dec_and_test(atomic_t *v)
  Int atomic_inc_and_test(atomic_t *v);

  结果等于0 返回真,否则返回假.


2、原子位的操作
  定义在 这些函数对某个普通的内存地址.
  可用的位操作:
  Void set_bit(nr,voie *addr);
  设置addr指向的数据项的nr位.
  
  Void clear_bit(nr,void *addr)
  清除addr指向的数据项的第nr位.

  Test_bit(nr,void *addr)
  返回当前的指定位.
  Int test_and_set_bit(nr,void *addr);
  设置nr位的同时返回原来的值

3、spinlock自旋锁
  自旋锁最多只能被一个可执行的线程持有,等待锁的进程采用忙循环等待.
  定义在 and  自旋锁可以在中断程序中使用.在这种情况下,其他代码要获得锁必须首先关闭中断.在配置内核时,可以选定CONFIG_DEBUG_SPINLOCK选项,打开spinlock的调试功能.
   1.spinlock的初始化
   静态:spinlock_t my_lock=SPIN_LOCK_UNSIGNED ;
   动态:void spin_lock_init(spinlock_t *lock);
  2.加锁函数
   Void spin_lock(spinlock_t *lock);
   Void spin_lock_irqsave(spinlock_t *lock,unsigned long flags);
   Void spin_lock_irq(spinlock_t *lock);
   Void spin_lock_bh(spinlock_t *lock);
   如果我们的一个自旋锁能够在中断处理程序中使用,或者在中断的下半部获得,则必 须使用禁止中断的spin_lock 形式.
  3.解锁函数
   Void spin_unlock(spinlock_t *lock);
   Void spin_unlock_irqsave(spinlock_t *lock,unsingned long flags);
   Void spin_unlock_irq(spinlock_t *lock);
   Void spin_unlock_bh(spinlock_t *lock);
  4.非阻塞的自旋锁
   Int spin_trylock(spinlock_t *lock);
   Int spin_trylock_bh(spinlock_t *lock);
   成功返回0.否则返回负.
4、读取者/写入者自旋锁
  1.初始化
   静态
   Rwlock_t my_rwlock = RW_LOCK_UNLOCKED
   动态
   Rwlock_t my_rwlock;
   Rwlock_init (&my_rwlock);
  2.加锁
   Read/write_lock();
   Read/wrte_lock_irq();
   Read/write_lock_irqsave();
   Read/write_lock_bh();
  3.解锁
   Read/write_unlock();
   Read/write_unlock_irq();
   Read/write_unlock_irqsave();
   Read/write_unlock_bh();
  4.其他   write_trylock();
   Rw_is_locked();
   注意:读/写锁机制要更照顾读者.当读者持有时,写者必须等待.如果有大量的读者,必定会引起写者处于饥饿状态.所以如果加锁时间不长,并且代码不会睡眠,可以利用自旋锁.如果加锁时间很长,或者代码在持有锁时可能睡眠,则最好使用信号量来枷锁.
5、信号量和互斥体
  信号量的特征:
   1.信号量适用于锁会被长期持有时,因为开销比较大.
   2.只有在进程的上下文才能获得信号量,因为获取信号量时可能导致睡眠,不适用中 断上下文.
   3.可以在持有信号量时去睡眠,因此可以在持有信号量的时候和用户空间同步.
   4.不能在持有信号量的同时持有自旋锁.
   5.信号量可以允许任意数量的持有者,而自旋锁在一个时刻只能有一个持有者.
   6.只拥有一个持有者的信号量称为互斥信号量
6、信号量的实现
  1.申明
   静态
   Static DECLARE_SEMAPHORE_GENERIC(name,count);
   或申明一个互斥信号量
   Static DECLARE_MUTEX(name);
   动态
   Struct semaphore sem;
   Sema_init(sem.count);
   Int_MUTEX(sem);
   Int_MUTEX_LOCKED(sem);
  2.获取信号量
   Void down(struct semaphore *sem)
   减小信号量的值.返回获得的信号量
   
   Int down_interruptible(struct semaphore *sem)
   在等待信号量时,可以被用户空间程序通过信号中断.如果操作被中断,则返回非零  值,调用者无法获得信号量.注意:调用时始终要检查返回值.
   Int down_trylock(struct semaphore *sem);
   不会休眠,如果不能获得信号量,立即返回一个非零值.
  3.释放信号量
   Viod up(struct semaphore *sem);
7、Array.completion 机制

  1.创建
   静态
   DECLARE_COMPLETION(my_completion);
   
   动态
   Struct completion my_completion;
   Init_completion(&my_completion);
  2.等待completion
   Void wait_for_completion(struct completion *c);
   执行一个非中断的等待,用户空间无法通过signal来中断这个进程.
  3.完成completion
   Void completion(struct completiong *)
  发信号唤醒任何等待任务.
8、如何禁内核抢占.
  1.preempt_disable()
   增加抢占记数值,从而禁止内核抢占.记数为0时,可以抢占.
  2.preempt_enable()
   减少抢占记数,并当该值降为0时检查和执行被挂起的需调度的任务.
  3.preempt_enable_no_resched();
   激活内核抢占,但不检查被挂起的需调度的任务
  4.preempt_count()
   返回抢占数.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值