lock_kernel

談到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操作。

以上部分轉載自:http://blog.chinaunix.net/uid-25588566-id-2231120.html

lock_kernel 的真實身份還需要內核編譯的 CONFIG_LOCK_KERNEL 確定.

內核使用了arch/arm/configs/s3c2410_defconfig作爲默認的配置文件,Code maturity level options 選項下沒有設置

CONFIG_LOCK_KERNEL 項.所以在這裏lock_kernel應該就是 #define lock_kernel() do { } while (0)的空操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章