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

LZ:

 

尝试用spin_lock_irqsave(),发现没有禁掉时钟中断,不知道我哪里理解错了?
kernel版本:

  1. uname -a 结果:
  2. Linux localhost.localdomain 2.6.18 #1 Sat Jul 19 13:06:00 EDT 2008 i686 i686 i386 GNU/Linux
复制代码



我的代码:

  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/spinlock.h>
  5. static spinlock_t my_spinlock;
  6. static int __init init_test()
  7. {
  8.         unsigned long flags;
  9.         spin_lock_init(&my_spinlock);
  10.         spin_lock_irqsave(&my_spinlock, flags);
  11.         return 0;
  12. }
  13. static void __exit init_exit()
  14. {
  15.         return;
  16. }
  17. module_init(init_test);
  18. module_exit(init_exit);
复制代码



加载module以后,通过这样的命令查看墙上时钟:

  1. #date; sleep 2; date
  2. 输出结果:
  3. Sun Apr 19 12:59:42 EDT 2009
  4. 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

  1. #include <linux/kernel.h>
  2. #include <linux/init.h>
  3. #include <linux/module.h>
  4. #include <linux/spinlock.h>
  5. #define IF_MASK 0x00000200
  6. static spinlock_t my_spinlock;
  7. static unsigned int is_interrupt_enable()
  8. {
  9.         unsigned long my_eflags;
  10.         asm volatile ("pushfl /n/t"
  11.         "popl %0"
  12.         :"=a"(my_eflags));
  13.         return (((my_eflags & IF_MASK) == 0) ? 0 : 1);
  14. }
  15. static int __init init_test()
  16. {
  17.         unsigned long flags;
  18.         spin_lock_init(&my_spinlock);
  19.         spin_lock_irqsave(&my_spinlock, flags);
  20.         printk("from kernelspace init: interrupt was enable : %d/n", is_interrupt_enable());
  21.         return 0;
  22. }
  23. static void __exit init_exit()
  24. {
  25.         return;
  26. }
  27. MODULE_LICENSE("GPL");
  28. module_init(init_test);
  29. module_exit(init_exit);
复制代码



编译以后生成my_spin_lock.ko

然后再写一段userspace program : test.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define IF_MASK 0x00000200
  4. #define CMD_LEN 100
  5. unsigned int is_interrupt_enable()
  6. {
  7.         unsigned long my_eflags;
  8.         asm volatile ("pushfl /n/t"
  9.         "popl %0 /n/t"
  10.         :"=a"(my_eflags));
  11.        
  12.         return (((my_eflags & IF_MASK) == 0) ? 0 : 1);
  13. }
  14. int main (int argc, char *argv[])
  15. {
  16.         if (argc != 2)
  17.         {
  18.                 printf("usersage: insmod your_kernel_module/n");
  19.                 return 0;       
  20.         }
  21.         char cmd[CMD_LEN];
  22.         memset(cmd, 0, sizeof(cmd));
  23.         sprintf(cmd, "insmod %s", argv[1]);
  24.         printf("from userspace, before insmod, inerrput is enable : %d/n", is_interrupt_enable());
  25.         system(cmd); /*insmod kernel module*/
  26.         printf("from userspace, after insmod, interrupt is enable : %d/n", is_interrupt_enable());       
  27.         memset(cmd, 0, sizeof(cmd));
  28.         sprintf(cmd, "rmmod %s", argv[1]);
  29.         system(cmd); /*rmmod kernel module*/
  30.        
  31.        
  32.         return 0;
  33. }
复制代码



编译以后生成test二进制文件

然后下命令:

  1. ./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被打开了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
spin_lock() 和 spin_lock_irqsave() 都是 Linux 内核中用于保护共享资源的自旋锁函数,它们的区别在于是否对中断进行处理。 spin_lock() 函数会获取自旋锁,并禁用本地 CPU 的中断。这意味着,如果在获取自旋锁的过程中发生了中断,中断处理程序将无法运行,直到自旋锁被释放。因此,spin_lock() 主要用于在中断被禁用的情况下保护共享资源,以防止其他 CPU 并发访问。 而 spin_lock_irqsave() 函数则会获取自旋锁,并保存本地 CPU 的中断状态。这意味着,在获取自旋锁的过程中,中断可以被触发,但是中断处理程序不能访问被保护的共享资源,因为它们也会尝试获取自旋锁。因此,spin_lock_irqsave() 主要用于在中断被启用的情况下保护共享资源。 在使用 spin_lock_irqsave() 函数,需要在获取自旋锁的同保存中断状态,并在释放自旋锁的同恢复中断状态,以避免出现中断状态被篡改的情况。常见的用法是: ```c spinlock_t my_lock; unsigned long flags; spin_lock_irqsave(&my_lock, flags); // 获取自旋锁并保存中断状态 // 在这里进行对共享资源的访问 spin_unlock_irqrestore(&my_lock, flags); // 释放自旋锁并恢复中断状态 ``` 总之,spin_lock() 适用于在禁用中断的情况下保护共享资源,而 spin_lock_irqsave() 适用于在启用中断的情况下保护共享资源,它们的使用方式略有不同,需要根据具体情况选择合适的函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

do2jiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值