linux lock函数,Linux lock_kernel()函数的分析。

这只是暂时的记录,以后会把它归类到start_kernel()函数的分析。在分析之前,我先要说说几个概念。

内核抢占:在2.6内核加入了抢占的能力,就是说调度程序有办法在一个内核级的任务正在执行的时候从新调度。但是必须要保证重新调度要安全,这样就要靠一把锁来保证了。

计数器(thread_info.[reempt_count):其实也可以把他叫成锁的,它的初值定义为0,每当使用锁的时候加1.

好了,我们现在来看看lock_kernel()的具体代码啦(2.6.10版本的)

#ifndef __LINUX_SMPLOCK_H

#define __LINUX_SMPLOCK_H

#include

#include

#include

#ifdef CONFIG_LOCK_KERNEL

#define kernel_locked()  (current->lock_depth >= 0)

extern int __lockfunc get_kernel_lock(void);

extern void __lockfunc put_kernel_lock(void);

/*

* Release/re-acquire global kernel lock for the scheduler

*/

#define release_kernel_lock(tsk) do {   /

if (unlikely((tsk)->lock_depth >= 0)) /

put_kernel_lock();  /

} while (0)

/*

* Non-SMP kernels will never block on the kernel lock,

* so we are better off returning a constant zero from

* reacquire_kernel_lock() so that the compiler can see

* it at compile-time.

*/

#ifdef CONFIG_SMP

#define return_value_on_smp return

#else

#define return_value_on_smp

#endif

static inline int reacquire_kernel_lock(struct task_struct *task)

{

if (unlikely(task->lock_depth >= 0))

return_value_on_smp get_kernel_lock();

return 0;

}

extern void __lockfunc lock_kernel(void) __acquires(kernel_lock);

extern void __lockfunc unlock_kernel(void) __releases(kernel_lock);

#else

#define lock_kernel()    do { } while(0)

#define unlock_kernel()    do { } while(0)

#define release_kernel_lock(task)  do { } while(0)

#define reacquire_kernel_lock(task)  0

#define kernel_locked()    1

#endif /* CONFIG_LOCK_KERNEL */

#endif /* __LINUX_SMPLOCK_H */

这个是对lock_kernel()函数的宏定义,#ifdef CONFIG_LOCK_KERNEL这里判断是否支持内核锁,如果不支持的话,lock_kernel就不做任何事情,我们来具体分析一下当配置了CONFIG_LOCK_KERNEL时lock_kernel()做些什么!我们直接看看这行代码extern void __lockfunc lock_kernel(void) __acquires(kernel_lock);

void __lockfunc lock_kernel(void)

{

int depth = current->lock_depth+1;

if (likely(!depth))

__lock_kernel();

current->lock_depth = depth;

}

这里可以看到有个标志lock_depth存在,对于这个标志,它的初始值为-1,如果自加后发现其实为0时,说明kernel_flag这个内核全局锁成功被这个进程所占有(current->lock_depth+1这个意味着0号进程的init_task.lock_depth加1)。接着就来到了__lock_kernel();这里的调用。我们来展开看看它的代码吧!

#ifdef CONFIG_PREEMPT

static inline void __lock_kernel(void)

{

preempt_disable();

if (unlikely(!_raw_spin_trylock(&kernel_flag))) {

/*

* If preemption was disabled even before this

* was called, there's nothing we can be polite

* about - just spin.

*/

if (preempt_count() > 1) {

_raw_spin_lock(&kernel_flag);

return;

}

/*

* Otherwise, let's wait for the kernel lock

* with preemption enabled..

*/

do {

preempt_enable();

while (spin_is_locked(&kernel_flag))

cpu_relax();

preempt_disable();

} while (!_raw_spin_trylock(&kernel_flag));

}

}

#else

/*

* Non-preemption case - just get the spinlock

*/

static inline void __lock_kernel(void)

{

_raw_spin_lock(&kernel_flag);

}

#endif

看到一上来就对CONFIG_PREEMPT进行判断,这个是判断内核是否支持抢占。如果是抢占大的话,就执行上面的__lock_kernel(),我们来看看第一行语句, preempt_disable();

#define preempt_disable() /

do { /

inc_preempt_count(); /

barrier(); /

} while (0)

我们来看看inc_preempt_count();这个函数是什么内容。

#define inc_preempt_count() /

do { /

preempt_count()++; /

} while (0)

我再进一步再往里看看。

#define preempt_count() (current_thread_info()->preempt_count)

终于看到了是对current_thread_info()->preempt_count自增。(在start_kernel来说就是init_thread_info.preempt_count加1)这样我们又回到了__lock_kernel函数了,对于下面代码的分析不太清楚,这里就不进行讲解了。接着我们来到了没有进行宏定义的else部分。

#else

/* * Non-preemption case - just get the spinlock */static inline void __lock_kernel(void){ _raw_spin_lock(&kernel_flag);}#endif这里就是简单的对kernel_flag这个全局变量加锁。好了,到这里我们算是把lock_kernel()分析了一遍了。其实总的来说,对于有抢占的,我们就不用用kernel_flag这个全局变量。这个全局变量其实是在2.4内核没有抢占功能内核的代码使用的。对于lock_kernel的分析就只是理解这么多,以后了解了跟多再来完善!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值