- #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操作。
以上部分轉載自: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)的空操作。