自旋锁

http://www.cnblogs.com/jesse123/archive/2011/07/01/2095388.html


瞎旋个啥,咋不去休眠、挂起呢?因为一些代码是大忙人,闲不得,更是停不得,就在门口自己玩死循环,急切的等待屋子里的人出来把锁给自己。

关于锁,最常使用的便是:自旋锁与信号量。先贴些实例,来点感性的认识。

-- include/linux/spinlock_types.h --
 
typedef  struct  {
     raw_spinlock_t raw_lock;
#ifdef CONFIG_GENERIC_LOCKBREAK
     unsigned int  break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
     unsigned int  magic, owner_cpu;
     void  *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
     struct  lockdep_map dep_map;
#endif
} spinlock_t;
 
 
typedef  struct  {
     volatile  unsigned int  lock;
} raw_spinlock_t;

以上是2.6.32中的定义。raw_spinlock_t在2.6.39中的定义:

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;
 
 
typedef  struct  raw_spinlock {
     arch_spinlock_t raw_lock;
#ifdef CONFIG_GENERIC_LOCKBREAK
     unsigned int  break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
     unsigned int  magic, owner_cpu;
     void  *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
     struct  lockdep_map dep_map;
#endif
} raw_spinlock_t;
 
 
typedef  struct  {
     volatile  unsigned int  lock;
} arch_spinlock_t;

大体上就是将struct raw_spinlock变肥了而已,对于我们而言,该吃吃,该睡睡,平时如何写代码,现在依旧如何写。只要volatile unsigned int lock在就好。

关于lock变量,涉及到一个“排队自旋锁“的问题,将lock分为三部分:高16位(一般未用),第16位再一分为二(next域,owner域)。
简单的说,申请自旋锁,next++;释放自旋锁,owner++;
if (next<未增值前> == owner)
     能申请自旋锁
else
     不能申请自旋锁

spinlock_t lock = SPIN_LOCK_UNLOCKED;
 
int  __init my_init( void )
{  
     /*输出宏SPIN_LOCK_UNLOCKED的相关信息*/
     printk( "<0>SPIN_LOCK_UNLOCKED: %d\n" ,SPIN_LOCK_UNLOCKED.raw_lock.rlock);
     
     spin_lock_init( &lock );  //初始化自旋锁
     printk( "<0>after init, lock: %d\n" ,lock.raw_lock.rlock);
     
     printk( "<0>\n" );
 
     spin_lock( &lock );      //第一次获取自旋锁
     printk( "<0>first spin_lock, lock: %d\n" ,lock.raw_lock.rlock);
     spin_unlock( &lock );    //第一次释放自旋锁
     printk( "<0>first spin_unlock, lock: %d\n" ,lock.raw_lock.rlock);
 
     printk( "<0>\n" );
 
     spin_lock( &lock );      //第二次获取自旋锁
     printk( "<0>second spin_lock, lock: %d\n" ,lock.raw_lock.rlock);
     spin_unlock( &lock );    //第二次释放自旋锁
     printk( "<0>second spin_unlock, lock: %d\n" ,lock.raw_lock.rlock);
 
     return  0;
}

加载结果:

Return

加锁是主菜,当然还会有一些附属功能(irq)一并执行,比如下面的三个实例:

(1)

(2)

(3)

再介绍一个try_lock:

            -------trylock的特点在于会有返回值。

spinlock_t lock = SPIN_LOCK_UNLOCKED;
int  ret;
 
int  my_function( void  * argc)
{
     printk( "<0>\nin child, the current pid is:%d\n" ,current->pid);      //显示子进程PID
     ret = spin_trylock( &lock );
     if ( ret == 1 )
     {
         spin_unlock( &lock );
     }
     else
     {
         printk( "<0>spin_trylock could't get the lock!\n" );
         printk( "<0>need the parent to unlock.\n\n" );
     }
     return  0;
}
 
 
 
int  __init spin_trylock_init( void )
{
     int  ret0;
 
     printk( "<0>in parent, the current pid is:%d\n" ,current->pid);   //显示父进程PID
 
     spin_lock_init( &lock );
     spin_lock( &lock );       //获取自旋锁
 
     ret0 = kernel_thread(my_function,NULL,CLONE_KERNEL);
 
 
     spin_unlock( &lock );    //释放自旋锁
     printk( "<0>parent unlock!\n" );
 
     return  0;
}

  

  

-----------

读写自旋锁
-----------

复制代码
typedef  struct  {
raw_rwlock_t raw_lock;
#ifdef CONFIG_GENERIC_LOCKBREAK
unsigned 
int  break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
unsigned 
int  magic, owner_cpu;
void * owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct  lockdep_map dep_map;
#endif
} rwlock_t;


typedef 
struct  {
volatile  unsigned  int lock ;
} raw_rwlock_t;
复制代码

读写锁当然也有个lock,低24位为读者计数器(0~23)。
24位为“未锁“标志字段
其他未用。

未锁置1,表示此时锁没人拿。
未锁置0,其他也为0,表示写者掌控锁。
未锁置0,低24位有值,表示读者掌控锁,读者的个数表示有点特别,就是:
一个读者,则:0x00ffffff
两个读者,则:0x00fffffe

以此列推,大伙儿都看得出来。

最后来个实例,帮助理解:

rwlock_t rwlock = RW_LOCK_UNLOCKED;
 
int  __init write_trylock_init( void )
{
     int  ret;
     rwlock_init( &rwlock );     //读写自旋锁初始化
     read_lock( &rwlock );       //读者申请得到读写锁rwlock
     /* 输出读写自旋锁lock字段信息*/
     printk( "<0>after read_lock,lock: 0x%x\n" ,rwlock.raw_lock.lock);
     
     printk( "<0>\n" );
     ret = write_trylock( &rwlock );  //写者试图获得自旋锁
     if ( ret == 1 )
     {  
         printk( "<0>after write_trylock, lock: 0x%x\n" ,rwlock.raw_lock.lock);
         write_unlock( &rwlock );
         printk( "<0>after write_unlock, lock: 0x%x\n" ,rwlock.raw_lock.lock);
     }  
     else
     {  
         printk( "<0>write_trylock could't get the lock!\n" );
     }  
     
     printk( "<0>\n" );
     read_unlock( &rwlock );    //读者释放读写锁rwlock
     printk( "<0>after read_unlock,lock: 0x%x\n" ,rwlock.raw_lock.lock);
 
     return  0;
}

加载结果:

当然,kernel里的锁还有许多,顺序锁啊,信号量啊什么。但基本都是那个样子。再说一个completioin,这个东西初次看到有点唬人,先来个实例:

struct  completion {
     unsigned int  done;
     wait_queue_head_t  wait;
};
 
--------------------------------
 
static  struct  completion comple;
 
int  my_function( void  * argc)
{
     wait_queue_head_t head;
     wait_queue_t data;
     printk( "<0>in the kernel thread function!\n" );
 
     init_waitqueue_head(&head);
     init_waitqueue_entry(&data,current);
     add_wait_queue(&head,&data);
 
     sleep_on_timeout(&head,10);
 
     printk( "<0>the current pid is:%d\n" ,current->pid);
     printk( "<0>the state of the parent is:%ld\n" ,current->real_parent->state);
     complete(&comple);     //这里若不执行此函数,之前的wait_for_completioin便会一直堵死在那里
     printk( "<0>out the kernel thread function\n" );
     return  0;
}  
     
 
static  int  __init wait_for_completion_init( void )
{  
     int  result;
     wait_queue_t data;
     printk( "<0>into wait_for_completion_init.\n" );             
     result=kernel_thread(my_function, NULL, CLONE_KERNEL);
     
     struct  pid * kpid=find_get_pid(result);
     struct  task_struct * task=pid_task(kpid,PIDTYPE_PID);
 
     init_completion(&comple);    //初始化好变量,记得变量里还包含个:wait_queue_head_t
 
     init_waitqueue_entry(&data, task);
     __add_wait_queue_tail(&(comple.wait), &data);    //加入这个队列头
 
     wait_for_completion(&comple);    //等待,起到同步作用
 
     printk( "<0>the result of the kernel_thread is :%d\n" ,result);
     printk( "<0>the current pid is:%d\n" ,current->pid);
     printk( "<0>out wait_for_completion_init.\n" );
     return  0;
}

completion是同步用的,和等待队列放在一起,自然就露出了她的本来面目~

好了,就先说这么些。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值