关于锁,最常使用的便是:自旋锁与信号量。先贴些实例,来点感性的认识。
-- include/linux/spinlock_types.h --
typedef struct {
typedef struct {
#ifdef CONFIG_GENERIC_LOCKBREAK
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#endif
} spinlock_t;
typedef struct {
} 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;
# define LOCK_PADSIZE (offsetof(struct raw_spinlock, dep_map))
#endif
} spinlock_t;
typedef struct raw_spinlock {
#ifdef CONFIG_GENERIC_LOCKBREAK
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#endif
} raw_spinlock_t;
typedef struct {
} 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)
{
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");
{
}
加载结果:
Return
[ 4123.219758] SPIN_LOCK_UNLOCKED: 0
[ 4123.219762] after init, lock: 0
[ 4123.219764]
[ 4123.219765] first spin_lock, lock: 256
[ 4123.219768] first spin_unlock, lock: 257
[ 4123.219770]
[ 4123.219771] second spin_lock, lock: 513
[ 4123.219774] second spin_unlock, lock: 514
加锁是主菜,当然还会有一些附属功能(irq)一并执行,比如下面的三个实例:
[ 4123.219758] SPIN_LOCK_UNLOCKED: 0
[ 4123.219762] after init, lock: 0
[ 4123.219764]
[ 4123.219765] first spin_lock, lock: 256
[ 4123.219768] first spin_unlock, lock: 257
[ 4123.219770]
[ 4123.219771] second spin_lock, lock: 513
[ 4123.219774] second spin_unlock, lock: 514
加锁是主菜,当然还会有一些附属功能(irq)一并执行,比如下面的三个实例:
(1)
int __init spin_lock_bh_init(void)
{
spinlock_t
lock =
SPIN_LOCK_UNLOCKED;
spin_lock_init( &lock
);
//初始化自旋锁
printk("<0>in_softirq():%ld\n",
in_softirq()); //输出软中断计数
{
}
--------------------------------------
[ 5065.951735] in_softirq():0
[ 5065.951739] lock........
[ 5065.951741] in_softirq():256
[ 5065.951743] unlock........
[ 5065.951745] in_softirq():0
(2)
int __init spin_lock_irq_init(void)
{
spinlock_t
lock = SPIN_LOCK_UNLOCKED;
{
}
---------------------------------------
[ 5747.407543] lock........
[ 5747.407548] irqs_disabled():1
[ 5747.407550] unlock........
[ 5747.407552] irqs_disabled():0
(3)
int __init spin_lock_irqsave_init(void)
{
unsigned
long flags = 0;
{
}
--------------------------------------
[ 6197.981793] lock........
[ 6197.981798] irqs_disabled():1
[ 6197.981800] flags = 0x200296
[ 6197.981802] unlock........
[ 6197.981804] irqs_disabled():0
再介绍一个try_lock:
-------trylock的特点在于会有返回值。
spinlock_t lock = SPIN_LOCK_UNLOCKED;
int ret;
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;
{
}
-----------
读写自旋锁
-----------
读写锁当然也有个lock,低24位为读者计数器(0~23)。
24位为“未锁“标志字段
其他未用。
未锁置1,表示此时锁没人拿。
未锁置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 intlock;
} raw_rwlock_t;
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 intlock;
} raw_rwlock_t;
复制代码
为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
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);
{
}
加载结果:
[ 9106.498749] after read_lock,lock:
0xffffff
[ 9106.498753]
[ 9106.498755] write_trylock could't get the lock!
[ 9106.498757]
[ 9106.498759] after read_unlock,lock: 0x1000000
[ 9106.498753]
[ 9106.498755] write_trylock could't get the lock!
[ 9106.498757]
[ 9106.498759] after read_unlock,lock: 0x1000000
当然,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");
{
}
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);
{
}
completion是同步用的,和等待队列放在一起,自然就露出了她的本来面目~
好了,就先说这么些。。。
本文详细介绍了内核中常用的锁机制,包括自旋锁与信号量的应用实例与原理,通过代码示例展示了如何在Linux内核环境下使用这些锁,并深入探讨了它们的工作机制及附加功能。

被折叠的 条评论
为什么被折叠?



