2014-06-05 40 views
0

我想用定时器多次调用一个函数。 为了实现这个,我使用了this的例子。它的默认工作没有任何错误。内核模块定时器杀死系统

当我将此代码片段集成到我的源代码中时,它导致内核恐慌(?)。发生长时间错误,虚拟机停止工作 。

印在控制台上的错误:

[ 1130.520474] [<c12bf6ae>] ? no_context+0x14b/0x155  
[ 1130.520474] [<c12bf7ca>] ? bad_area_nosemaphore+0xa/0xc      
[ 1130.520474] [<c12c7370>] ? do_page_fault+0x1bf/0x35e 
[ 1130.520474] [<c100d6bf>] ? show_trace_log_lvl+0x37/0x3d      
[ 1130.520474] [<c12c71b1>] ? vmalloc_fault+0x87/0x87      
[ 1130.520474] [<c12c5377>] ? error_code+0x67/0x6c        
[ 1130.520474] [<c12c306e>] ? __schedule+0x31/0x5a4        
[ 1130.520474] [<c100fa07>] ? sched_clock+0x9/0xd  
[ 1130.520474] [<c1051896>] ? sched_clock_local+0x10/0x14b 
[ 1130.520474] [<c102abe2>] ? test_tsk_need_resched+0xa/0x13 
[ 1130.520474] [<c102abe2>] ? test_tsk_need_resched+0xa/0x13    
[ 1130.520474] [<c102e59c>] ? check_preempt_curr+0x48/0x58      
[ 1130.520474] [<c121f462>] ? __napi_complete+0x1b/0x22       
[ 1130.520474] [<c12213f0>] ? napi_complete+0x25/0x31 
[ 1130.520474] [<f825d2d6>] ? e1000_clean+0x33e/0x35c [e1000] 
[ 1130.520474] [<c105daf5>] ? arch_local_irq_save+0xf/0x14 
[ 1130.520474] [<c12c45a2>] ? _raw_spin_lock_irq+0x9/0x12     
[ 1130.520474] [<c1042307>] ? run_timer_softirq+0x1eb/0x1f3     
[ 1130.520474] [<c107b86c>] ? __rcu_process_callbacks+0x5f/0x252    
[ 1130.520474] [<c103cfdb>] ? local_bh_enable+0x2/0x2    
[ 1130.520474] [<c103d0dc>] ? __do_softirq+0x101/0x12f 
[ 1130.520474] [<c103c6e8>] ? __local_bh_enable+0x37/0x67      
[ 1130.520474] <IRQ> [<c10cd712>] ? sys_write+0x58/0x61      
[ 1130.520474] [<c12c8e5f>] ? sysenter_do_call+0x12/0x28 

我想我的问题是返回先前的前一个新的呼叫被触发。

为了测试这一点,我修改了上面提到的定时器玩具例子:

int i; 

void timer1_routine(unsigned long data) 
{ 
    int no; 
    no=i; 
    i++; 
    printk(KERN_INFO "process %d starts",no); 

    msleep(5000); 

    printk(KERN_INFO "process %d ends",no); 

    mod_timer(&timer1, jiffies + HZ); /* restarting timer */ 
} 

这导致了同样的错误,所以我想,我的猜测是正确的:有两个电话之间的冲突。我的问题是如何避免这个问题,如果我不知道函数的执行需要多少时间?

回答

3

linux内核有两种主要类型的上下文:进程上下文和原子上下文。你习惯于在流程上下文中运行的东西。原子环境主要用于硬件和软件的中断。内核定时器从软件中断(原子上下文)运行。在原子上下文中运行的代码有一些限制,包括禁止睡眠。这解释了这次事故。

你几乎肯定想要一个workqueue而不是一个计时器。工作队列函数在进程上下文中执行,因此您可以进入休眠状态。如果你要在内核的这个级别工作,你真的需要阅读LDD3的这一章:http://lwn.net/images/pdf/LDD3/ch07.pdf

相关问题