LZ:
嘗試用spin_lock_irqsave(),發現沒有禁掉時鐘中斷,不知道我哪裡理解錯了?
kernel版本:
- uname -a 結果:
- Linux localhost.localdomain 2.6.18 #1 Sat Jul 19 13:06:00 EDT 2008 i686 i686 i386 GNU/Linux
複製代碼
My Code:
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/spinlock.h>
- static spinlock_t my_spinlock;
- static int __init init_test()
- {
- unsigned long flags;
- spin_lock_init(&my_spinlock);
- spin_lock_irqsave(&my_spinlock, flags);
- return 0;
- }
- static void __exit init_exit()
- {
- return;
- }
- module_init(init_test);
- module_exit(init_exit);
複製代碼
載入module以後,通過這樣的命令查看牆上時鐘:
- #date; sleep 2; date
- 輸出結果:
- Sun Apr 19 12:59:42 EDT 2009
- Sun Apr 19 12:59:44 EDT 2009
複製代碼
牆上時鐘仍然在變化,說明時鐘中斷沒有被禁掉。
但我理解的spin_lock_irqsave()會通過cli關掉所有IRQ,並且我在module中也沒有spin_unlock_irqrestore(),所以按理說在載入了這個module之後,系統就不會響應任何外部可屏蔽中斷了。但實際結果卻不是這樣。
我哪裡理解錯了呢?請各位指點,多謝!
解答:
寫了一段kernel module和 userspace program來驗證:
kernel module: my_spin_lock.c
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/spinlock.h>
- #define IF_MASK 0x00000200
- static spinlock_t my_spinlock;
- static unsigned int is_interrupt_enable()
- {
- unsigned long my_eflags;
- asm volatile ("pushfl /n/t"
- "popl %0"
- :"=a"(my_eflags));
- return (((my_eflags & IF_MASK) == 0) ? 0 : 1);
- }
- static int __init init_test()
- {
- unsigned long flags;
- spin_lock_init(&my_spinlock);
- spin_lock_irqsave(&my_spinlock, flags);
- printk("from kernelspace init: interrupt was enable : %d/n", is_interrupt_enable());
- return 0;
- }
- static void __exit init_exit()
- {
- return;
- }
- MODULE_LICENSE("GPL");
- module_init(init_test);
- module_exit(init_exit);
複製代碼
編譯以後產生my_spin_lock.ko
然後再寫一段userspace program : test.c
- #include <stdio.h>
- #include <stdlib.h>
- #define IF_MASK 0x00000200
- #define CMD_LEN 100
- unsigned int is_interrupt_enable()
- {
- unsigned long my_eflags;
- asm volatile ("pushfl /n/t"
- "popl %0 /n/t"
- :"=a"(my_eflags));
-
- return (((my_eflags & IF_MASK) == 0) ? 0 : 1);
- }
- int main (int argc, char *argv[])
- {
- if (argc != 2)
- {
- printf("usersage: insmod your_kernel_module/n");
- return 0;
- }
- char cmd[CMD_LEN];
- memset(cmd, 0, sizeof(cmd));
- sprintf(cmd, "insmod %s", argv[1]);
- printf("from userspace, before insmod, inerrput is enable : %d/n", is_interrupt_enable());
- system(cmd); /*insmod kernel module*/
- printf("from userspace, after insmod, interrupt is enable : %d/n", is_interrupt_enable());
- memset(cmd, 0, sizeof(cmd));
- sprintf(cmd, "rmmod %s", argv[1]);
- system(cmd); /*rmmod kernel module*/
-
-
- return 0;
- }
複製代碼
編譯以後產生test二進位檔案
然後下命令:
- ./test my_spin_lock.ko
複製代碼
運行結果:
QUOTE:from userspace, before insmod, interrupt is enable : 1
from kernelspace init: interrupt was enable : 0
from userspace, after insmod, interrupt is enable: 1
可見,運行了kernel module的init函數以後,interrupt確實被禁止了。然後返回到使用者態,interrupt被開啟了。