如何从IRQ范围内的非单片内核模块进行软重启?

时间:2012-03-15 21:25:24

标签: linux linux-kernel kernel reboot irq

我需要在内核中处理IRQ时重新启动。

我想调用/sbin/reboot二进制文件,但由于IRQ范围,我有限制。

代码如下:

#define MY_IRQ_ID       42

void __init             rebootmodule_init(void) {
    request_any_context_irq(MY_IRQ_ID, rebootmodule_irq_handler, IRQF_TRIGGER_FALLING, "irq-name", NULL);
}

irqreturn_t             rebootmodule_irq_handler(int irq, void *dev_id) {
    my_reboot();
    return IRQ_HANDLED;
}

void                    my_reboot(void) {
    int                 ret;
    char                *argv[2], *envp[4];

    argv[0] = "/sbin/reboot";
    argv[1] = NULL;
    envp[0] = "HOME=/";
    envp[1] = "PWD=/";
    envp[2] = "PATH=/sbin";
    envp[3] = NULL;
    ret = call_usermodehelper(argv[0], argv, envp, 0);
    printk(KERN_INFO "trying to reboot (ret = %d)", ret);
}

我可以在触发IRQ时看到printk(...)但是我有一些错误,即使我将/sbin/reboot替换为/bin/rm /tmp/its-not-working

我测试了其他方式进行重启,例如mvBoardReset()machine_halt()arm_pm_restart()pm_power_off()kill(1, SIGTSTP)reboot(),{{1我总是遇到IRQ范围之外没有的错误。

我真的想打电话给handle_sysrq('b'),因为它清理软复位。

感谢您的时间。

1 个答案:

答案 0 :(得分:5)

只是一个想法:你可以通过kthread_run()启动内核线程,通过wait_event()让它进入睡眠状态,通过wake_up()在IRQ处理程序中将其唤醒,运行你的东西(运行{内核线程中的{1}}或任何你想要的东西。这样的事情(完全未经测试):

/sbin/reboot

不要忘记处理模块#define MY_IRQ_ID 42 static DECLARE_WAIT_QUEUE_HEAD(wq); static volatile int showtime = 0; void my_reboot(void) { int ret; char *argv[2], *envp[4]; argv[0] = "/sbin/reboot"; argv[1] = NULL; envp[0] = "HOME=/"; envp[1] = "PWD=/"; envp[2] = "PATH=/sbin"; envp[3] = NULL; ret = call_usermodehelper(argv[0], argv, envp, 0); printk(KERN_INFO "trying to reboot (ret = %d)", ret); } static int my_thread(void *arg) { wait_event(&wq, showtime); my_reboot(); return 0; } irqreturn_t rebootmodule_irq_handler(int irq, void *dev_id) { showtime = 1; wake_up(&wq); return IRQ_HANDLED; } void __init rebootmodule_init(void) { kthread_run(my_thread, NULL, "my_module"); request_any_context_irq(MY_IRQ_ID, rebootmodule_irq_handler, IRQF_TRIGGER_FALLING, "irq-name", NULL); } 以及在内核线程被发送到休眠状态之前中断的情况。