您的位置:首页 > 其它

为什么我的spin_lock_irqsave()没有锁住时钟中断?

2013-04-15 23:03 555 查看
尝试用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

复制代码

我的代码:

#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被打开了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: