Chinaunix首页 | 论坛 | 博客
  • 博客访问: 42571
  • 博文数量: 8
  • 博客积分: 165
  • 博客等级: 入伍新兵
  • 技术积分: 96
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-21 16:54
文章分类

全部博文(8)

文章存档

2014年(1)

2013年(1)

2012年(1)

2011年(5)

分类: LINUX

2011-08-19 08:04:24

谈到lock_kernel,首先应该参看源码(此处所讲的是2.6.11版本的内核)中的include/linux/smp_lock.h文件。具体请参见该文件,在此处就不列出源码了
下面就开始分析了
  1. #ifdef CONFIG_LOCK_KERNEL
首先就是判断我们是否配置内核支持内核锁。当然分两种情况了,要么配置了,要么就没有要这种功能
先来看配置了内核锁之后的代码部分
  1. #define kernel_locked()        (current->lock_depth >= 0)

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

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

  1. void __lockfunc lock_kernel(void)
  2. {
  3.     struct task_struct *task = current;
  4.     int depth = task->lock_depth + 1;

  5.     if (likely(!depth))
  6.         /*
  7.          * No recursion worries - we set up lock_depth _after_
  8.          */
  9.         down(&kernel_sem);

  10.     task->lock_depth = depth;
  11. }

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

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

  1. DECLARE_MUTEX(kernel_sem);

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

  1. if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
  2. #define DECLARE_MUTEX(name) struct semaphore name=MUTEX

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

 

  1. #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
  2. define __DECLARE_SEMAPHORE_GENERIC(name,count) \
  3.     struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
  4. #define __SEMAPHORE_INITIALIZER(name, n)                \
  5. {                                    \
  6.     .count        = ATOMIC_INIT(n),                \
  7.     .sleepers    = 0,                        \
  8.     .wait        = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
  9. }

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

  1. struct semaphore {
  2.     atomic_t count;
  3.     int sleepers;
  4.     wait_queue_head_t wait;
  5. };
  1. typedef struct { volatile int counter; } atomic_t;
  2. /*此处通过typedef来重新定义一个标示符,其实就是一个整形的变量,但是为了用在多进程中,采用了volatile来修饰,至于为什么要定义成结构体,当然是为了提高类型检查了*/

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

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

  1. static inline void down(struct semaphore * sem)
  2. {
  3.     might_sleep();
  4.     __asm__ __volatile__(
  5.         "# atomic down operation\n\t"
  6.         LOCK "decl %0\n\t" /* --sem->count */
  7.         "js 2f\n"
  8.         "1:\n"
  9.         LOCK_SECTION_START("")
  10.         "2:\tlea %0,%%eax\n\t"
  11.         "call __down_failed\n\t"
  12.         "jmp 1b\n"
  13.         LOCK_SECTION_END
  14.         :"=m" (sem->count)
  15.         :
  16.         :"memory","ax");
  17. }

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

  1. #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
  2. #define might_sleep() __might_sleep(__FILE__, __LINE__)
  3. #else
  4. #define might_sleep() do {} while(0)
  5. #endif

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

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

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

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

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

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

 

 

 

阅读(3637) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:linux进程task_struct结构体中的state域

给主人留下些什么吧!~~