LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2072|回复: 14

内核定时器小程序的错误

[复制链接]
发表于 2007-6-1 12:12:09 | 显示全部楼层 |阅读模式
我编了个内核定时器的小程序。编译通过了。不过insmod后, 系统会死机。。不知道错在哪。我是按书上的顺序做的啊。。。。。。代码如下
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/timer.h>
MODULE_LICENSE("GPL");

static int  hello_init(void) {
void timer_test(unsigned long data);
struct timer_list my_timer;
init_timer(&my_timer);
my_timer.expires= jiffies + 5000;
my_timer.data=0;
my_timer.function=timer_test;
add_timer(&my_timer);
   return 0;
}
void timer_test(unsigned long data) {
printk("test!\n");
}


static void hello_exit(void) {
   printk(KERN_ALERT "Goodbye, cruel world\n");
}


module_init(hello_init);

module_exit(hello_exit);

估计初始化定时器的错误
发表于 2007-6-1 12:28:04 | 显示全部楼层
你看的是LKD吧? 我觉得后面应该还要加上schedule(). 不然就一直在这个程序中了.
建议你可以看看schedule_timeout()这个函数. 我看这里面就加了schedule()的.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-6-1 16:26:41 | 显示全部楼层
Post by scutan
你看的是LKD吧? 我觉得后面应该还要加上schedule(). 不然就一直在这个程序中了.
建议你可以看看schedule_timeout()这个函数. 我看这里面就加了schedule()的.

后边有return 0语句啊。只是添加了个异步的定时器,就算我编的是个死循环,内核会卡在这。不可能连中断也屏蔽了吧?何况还有内核抢占呢。到底怎么回事?
回复 支持 反对

使用道具 举报

发表于 2007-6-1 22:05:51 | 显示全部楼层
在add_timer()中会调用自旋锁spin_lock_irq(),它会禁止本地中断,同时由于调用了自旋锁,也会关闭内核抢占的.
可能是什么地方引起了死锁吧!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-6-2 12:57:14 | 显示全部楼层
Post by scutan
在add_timer()中会调用自旋锁spin_lock_irq(),它会禁止本地中断,同时由于调用了自旋锁,也会关闭内核抢占的.
可能是什么地方引起了死锁吧!

add timer()要么成功。成功后一定回释放锁,要么失败。失败了也该释放锁啊。我的代码完全是按照规范写的。郁闷
回复 支持 反对

使用道具 举报

发表于 2007-6-4 09:49:58 | 显示全部楼层
参考了LDD,写了一个比较简单的定时器.你看看.

  1. #include<linux/init.h>
  2. #include<linux/sched.h>
  3. #include<linux/module.h>
  4. #include<linux/jiffies.h>
  5. #include<asm/io.h>
  6. #include<linux/timer.h>
  7. #include<linux/wait.h>

  8. MODULE_LICENSE("GPL");

  9. static DECLARE_WAIT_QUEUE_HEAD(wq);
  10. static int flag = 0;
  11. struct timer_list my_timer;

  12. void timer_test(unsigned long data)
  13. {
  14.         printk("this is a test\n");
  15.         flag = 1;
  16.         wake_up_interruptible(&wq);
  17. }

  18. static int __init hello_init(void)
  19. {
  20.         init_timer(&my_timer);
  21.         my_timer.expires = jiffies + 5000;
  22.         my_timer.data = 0;
  23.         my_timer.function = timer_test;
  24.         add_timer(&my_timer);
  25.         wait_event_interruptible(wq, flag != 0);
  26.         flag = 0;
  27.         return 0;
  28. }

  29. static void __exit hello_exit(void)
  30. {
  31.         del_timer(&my_timer);
  32.         printk(KERN_ALERT "Goodbye\n");
  33. }

  34. module_init(hello_init);
  35. module_exit(hello_exit);

复制代码
回复 支持 反对

使用道具 举报

发表于 2007-6-4 10:22:26 | 显示全部楼层
我觉得那种方法不成功的原因是,你的这个进程都已经退出了,然后又要来触发那个定时器,而此时这个定时器的数据结构随着这个进程也一起没有了,所以就出现了死机.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-6-4 11:21:47 | 显示全部楼层
定时器不是由特定进程触发的,而是由时钟中断啊。是在时钟中断的下半部被触发执行的。
看了楼上的代码。终于找到了bug
我的time_list my_timer是在函数栈中分配的。hello_init返回后。栈会清空。所以根本找不到my_timer结构。把my_timer拿到hello_init外。运行成功,没死机。
谢谢楼上的参与。希望和你一起提高!
回复 支持 反对

使用道具 举报

发表于 2007-6-4 12:23:55 | 显示全部楼层
嗯.对,如你所说,将my_timer设为全局变量,不需要等待队列也同样可以成功.而且你这种方式在加载之后,进程可以退出,我那种使用等待队列的方式,在加载了之后,进程是不会退出的,只是从运行队列放到了等待队列之中.只有将定时器的函数运行之后才会退出.

不客气, 我也是初学者, 加油!
回复 支持 反对

使用道具 举报

发表于 2007-6-4 12:36:22 | 显示全部楼层

dddddddddddddddd

参考了LDD,写了一个比较简单的定时器.你看看.

#include<linux/init.h>
#include<linux/sched.h>
#include<linux/module.h>
#include<linux/jiffies.h>
#include<asm/io.h>
#include<linux/timer.h>
#include<linux/wait.h>

MODULE_LICENSE("GPL");

static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag = 0;
struct timer_list my_timer;

void timer_test(unsigned long data)
{
        printk("this is a test\n");
        flag = 1;
        wake_up_interruptible(&wq);
}

static int __init hello_init(void)
{
        init_timer(&my_timer);
        my_timer.expires = jiffies + 5000;
        my_timer.data = 0;
        my_timer.function = timer_test;
        add_timer(&my_timer);
        wait_event_interruptible(wq, flag != 0);
        flag = 0;
        return 0;
}

static void __exit hello_exit(void)
{
        del_timer(&my_timer);
        printk(KERN_ALERT "Goodbye\n");
}

module_init(hello_init);
module_exit(hello_exit);

不错啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表