linux下lock函数,Linux中的lock_kernel函数分析

谈到lock_kernel,首先应该参看源码(此处所讲的是2.6.11版本的内核)中的include/linux/smp_lock.h文件。具体请参见该文件,在此处就不列出源码了

下面就开始分析了

#ifdef CONFIG_LOCK_KERNEL

首先就是判断我们是否配置内核支持内核锁。当然分两种情况了,要么配置了,要么就没有要这种功能

先来看配置了内核锁之后的代码部分

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

上面的宏是判断内核是否已经被锁,通过什么判断呢?通过当前的进程的lock_depth这个变量的值来判断,提示:current就是当前正在执行的进程的tast_struct类型的指针变量。具体可参见include/linux/sched.h文件关于task_struct结构体的定义。如果这个变量的值大于0,那么内核就被锁住了,否则就没有锁。在初始化中lock_depth的值=-1.

现在就看看lock_kernel函数的实现部分吧

void __lockfunc lock_kernel(void)

{

struct task_struct *task = current;

int depth = task->lock_depth + 1;

if (likely(!depth))

/*

* No recursion worries - we set up lock_depth _after_

*/

down(&kernel_sem);

task->lock_depth = depth;

}

从上面的代码中,首先将当前进程的lock_depth变量+1,然后判断depth变量的值是否为0,为什么是0?其实前面已经提到了,lock_depth的值初始化是-1,在此加上了1,当然是0了,那么if这个判断语句就成立了。

在分析down函数之前我们需要注意下kernel_sem变量是什么?

DECLARE_MUTEX(kernel_sem);

又出来一个DECLARE_MUTEX宏,我们追踪一下子

if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)

#define DECLARE_MUTEX(name) struct semaphore name=MUTEX

显然这个不是,因为我当前的版本内核是2.6.11,而不是低于2.4的。

#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)

define __DECLARE_SEMAPHORE_GENERIC(name,count) \

struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)

#define __SEMAPHORE_INITIALIZER(name, n)                \

{                                    \

.count        = ATOMIC_INIT(n),                \

.sleepers    = 0,                        \

.wait        = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \

}

从上面的代码就可以看出这个宏的作用了,就是对semaphore这个结构体进行初始化。

struct semaphore {

atomic_t count;

int sleepers;

wait_queue_head_t wait;

};

typedef struct { volatile int counter; } atomic_t;

/*此处通过typedef来重新定义一个标示符,其实就是一个整形的变量,但是为了用在多进程中,采用了volatile来修饰,至于为什么要定义成结构体,当然是为了提高类型检查了*/

通过上面的一些基本信息,我们就来深入看一下怎样初始化了这个结构体变量。首先就是将count变量的值初始化为1,sleepers为0,wait变量通过宏来初始化了,主要说明了这个进程没有自旋,而且将等待队列初始化了空循环队列。具体可以查看内核源码。

有了对kernel_sem变量的了解,接着就是执行down函数。我们来看看down函数:

static inline void down(struct semaphore * sem)

{

might_sleep();

__asm__ __volatile__(

"# atomic down operation\n\t"

LOCK "decl %0\n\t" /* --sem->count */

"js 2f\n"

"1:\n"

LOCK_SECTION_START("")

"2:\tlea %0,%%eax\n\t"

"call __down_failed\n\t"

"jmp 1b\n"

LOCK_SECTION_END

:"=m" (sem->count)

:

:"memory","ax");

}

哇,是内嵌汇编语言。先来看看might_sleep宏

#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP

#define might_sleep() __might_sleep(__FILE__, __LINE__)

#else

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

#endif

此处仅仅提供了might_sleep宏的实现代码而没有进行深入的探究。有兴趣的可以深入探究,__might_sleep函数定义在kernel/sched.c源文件中

上面的down函数主要功能就是对semaphore结构体中的count变量变量进行减1操作。

截至此处我们才弄清楚了lock_kernel这个函数到底做了什么工作,现在总结一下:

首先让lock_depth变量自增,然后判断结果是否为0,如果是,则进行对信号量的自减操作,类似于PV操作(如果学习了操作系统的同学了).

以上就是我对lock_kernel函数的一些理解了,分析不正确的地方还望有人能够指出,我一定感激不尽。

至于其他的函数我会陆续进行分析并贴出来,望大家能够互相学习,指正错误。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值