【问题标题】:linux/timer.h setup_timer() expiration function not working?linux/timer.h setup_timer() 过期功能不起作用?
【发布时间】:2011-01-17 10:37:00
【问题描述】:

所以我的 setup_timer() 中的 TimerExpire 函数会引起巨大的恐慌(将在下面发布),而对 TimerExpire() 的常规函数​​调用实际上会打印出我的输入。

void TimerExpire(char* data)
{
    printk("Timer Data: %s\n", data);
}

setup_timer(&my_timer, TimerExpire, (char *)args);
printk("Made timer: %s\n", (char *)args);
TimerExpire((char *)args);

有人知道为什么吗?

这是错误输出(顺便说一下,这是在一个 gumstix verdex 模拟器上,它是一个 linux 内核):

# Unable to handle kernel paging request at virtual address be940eb2
pgd = c0004000
[be940eb2] *pgd=00000000
Internal error: Oops: 35 [#1]
Modules linked in: mytimer ipv6 pxa2xx_cs pxa2xx_core pcmcia pcmcia_core firmware_class pxamci mmc_block mmc_core
CPU: 0
PC is at strnlen+0x20/0x34
LR is at vsnprintf+0x318/0x5c8
pc : [<c00d6be8>]    lr : [<c00d7d4c>]    Not tainted
sp : c01b9d88  ip : c01b9d98  fp : c01b9d94
r10: 00000000  r9 : c01ca148  r8 : ffffffff
r7 : c01ce468  r6 : c01c9d54  r5 : be940eb2  r4 : c01b9e94
r3 : c01a0808  r2 : be940eb2  r1 : fffffffe  r0 : be940eb2
Flags: NzCv  IRQs off  FIQs on  Mode SVC_32  Segment kernel
Control: 7977
Table: A3488000  DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc01b8258)
Stack: (0xc01b9d88 to 0xc01ba000)
9d80:                   c01b9de4 c01b9d98 c00d7d4c c00d6bd4 00000000 c01b9e4c 
9da0: 00000989 00000033 c01b9e24 00000400 c01c9d48 bf06523d 000080d5 00000400 
9dc0: bf065054 c01b9e94 c01ce468 00000000 69054114 c01b8000 c01b9dfc c01b9de8 
9de0: c00d814c c00d7a40 00000000 bf065230 c01b9e74 c01b9e00 c00381b8 c00d8140 
9e00: c01b9e24 20000193 00000001 60000113 00000000 c0276db0 00000000 00000003 
9e20: c01b9e3c c01b9e30 c003468c c0034508 c01b9e6c c01b9e40 c0033268 c0034684 
9e40: 00000989 20000193 c01b9ec4 00000100 bf065054 bf065944 c01ce468 00000000 
9e60: 69054114 c01b8000 c01b9e8c c01b9e78 c003845c c003810c bf065944 c01b9e94 
9e80: c01b9eac c01b9ea0 bf06504c c0038444 bf065230 be940eb2 c01b9ec8 60000113 
9ea0: c01b9ebc c01b9eb0 bf065064 bf065040 c01b9ef4 c01b9ec0 c003ffb8 bf065060 
9ec0: bf065960 c0040d08 c01b9ec8 c01b9ec8 00000001 c01ce264 0000000a c01e1d7c 
9ee0: a001419c a0014168 c01b9f14 c01b9ef8 c003c7c4 c003fe60 69054114 0000001a 
9f00: c01ba680 00000000 c01b9f24 c01b9f18 c003cb88 c003c770 c01b9f44 c01b9f28 
9f20: c002957c c003cb50 c00086f4 ffffffff c01b9f7c 04000000 c01b9f9c c01b9f48 
9f40: c0028830 c0029540 00000001 c01b8000 a0000013 20000013 c0029d44 c01b8000 
9f60: c00153e8 c01e1d7c a001419c 69054114 a0014168 c01b9f9c c01b9f90 c01b9f90 
9f80: c0029d8c c0029d98 20000013 ffffffff c01b9fb4 c01b9fa0 c0029b1c c0029d50 
9fa0: c01dc20c c01c88b0 c01b9fc4 c01b9fb8 c0028138 c0029af0 c01b9ff4 c01b9fc8 
9fc0: c0008adc c0028120 c00083e4 00000000 00000000 c00153e8 00000000 00007975 
9fe0: c01c8964 c01be264 00000000 c01b9ff8 a0008030 c00088bc 00000000 00000000 
Backtrace: 
[<c00d6bc8>] (strnlen+0x0/0x34) from [<c00d7d4c>] (vsnprintf+0x318/0x5c8)
[<c00d7a34>] (vsnprintf+0x0/0x5c8) from [<c00d814c>] (vscnprintf+0x18/0x24)
[<c00d8134>] (vscnprintf+0x0/0x24) from [<c00381b8>] (vprintk+0xb8/0x334)
 r4 = BF065230 
[<c0038100>] (vprintk+0x0/0x334) from [<c003845c>] (printk+0x28/0x30)
[<c0038434>] (printk+0x0/0x30) from [<bf06504c>] (PrintMessage+0x18/0x20 [mytimer])
 r3 = 60000113  r2 = C01B9EC8  r1 = BE940EB2  r0 = BF065230
[<bf065034>] (PrintMessage+0x0/0x20 [mytimer]) from [<bf065064>] (TimerExpire+0x10/0x14 [mytimer])
[<bf065054>] (TimerExpire+0x0/0x14 [mytimer]) from [<c003ffb8>] (run_timer_softirq+0x164/0x1e8)
[<c003fe54>] (run_timer_softirq+0x0/0x1e8) from [<c003c7c4>] (__do_softirq+0x60/0xd4)
[<c003c764>] (__do_softirq+0x0/0xd4) from [<c003cb88>] (irq_exit+0x44/0x4c)
 r6 = 00000000  r5 = C01BA680  r4 = 0000001A 
[<c003cb44>] (irq_exit+0x0/0x4c) from [<c002957c>] (asm_do_IRQ+0x48/0x60)
[<c0029534>] (asm_do_IRQ+0x0/0x60) from [<c0028830>] (__irq_svc+0x30/0x80)
 r6 = 04000000  r5 = C01B9F7C  r4 = FFFFFFFF 
[<c0029d44>] (default_idle+0x0/0x5c) from [<c0029b1c>] (cpu_idle+0x38/0x54)
[<c0029ae4>] (cpu_idle+0x0/0x54) from [<c0028138>] (rest_init+0x24/0x2c)
 r5 = C01C88B0  r4 = C01DC20C 
[<c0028114>] (rest_init+0x0/0x2c) from [<c0008adc>] (start_kernel+0x22c/0x284)
[<c00088b0>] (start_kernel+0x0/0x284) from [<a0008030>] (0xa0008030)
Code: ea000000 e2800001 e2511001 3a000002 (e5d03000) 
Kernel panic - not syncing: Aiee, killing interrupt handler!

【问题讨论】:

    标签: linux timer kernel kernel-module


    【解决方案1】:

    这里只是一个非常疯狂的猜测。但我建议通过

    缩小范围
    • 首先从计时器函数中删除 printk(以确保 printk() 是有罪的)
    • 如果这样可以使 printk 打印一个静态字符串(不带参数),请了解您是否可以从该上下文中 printk(可能是 printk 在 softirq 上下文中不被欣赏)
    • 然后开始查看数据是否可以访问,你传递一个指向某个字符串的指针,你知道那个字符串还存在吗?它是一个全局字符串(因此可访问,或不可访问)。

    如果您查看timer.h,指向数据的指针刚刚被存储,因此如果该指针超出范围或变得不可访问,我希望 printk 会出现这种行为。

    【讨论】:

    • 我想我明白了……但我仍然需要对其进行编码,看看我是否正确。我的 args 来自用户空间......所以我需要 copy_from_user 因为我的内核模块在内核空间中。
    • copy_from_user 是不够的,您需要将其复制到计时器回调能够找到它的位置。
    【解决方案2】:

    谁控制指针data指向的内存?在你的计时器关闭时,该内存是否已被回收?

    也许您应该复制该数据,在某个可以保证它以后仍然有效的地方。

    为了测试,检查TimerExpire() 是否可以打印没有字符串的消息。如果这可行,那么您就知道问题出在指针上,而不是计时器上。

    【讨论】:

    • 你说得对。这是指针的问题。我在发布之前尝试过它,尽管如果我将它转换为 int,它可以工作并打印。但是在我上面对 amo-ej1 的评论中,我提到它可能是因为 args 来自用户空间,我正在尝试在内核空间中使用它。
    猜你喜欢
    • 2014-03-28
    • 2019-08-24
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    相关资源
    最近更新 更多