2012-03-15 2 views
2

Мне нужно перезагрузиться при обработке 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); 
} 

Я могу видеть printk(...) когда прерывание срабатывает, но у меня есть некоторые ошибки, даже если я заменю /sbin/reboot на /bin/rm /tmp/its-not-working.

я тестировал другой способ сделать перезагрузку, как mvBoardReset(), machine_halt(), arm_pm_restart(), pm_power_off(), kill(1, SIGTSTP), reboot(), handle_sysrq('b'), у меня всегда есть ошибки, которые не имеют за рамки IRQ.

Я действительно хочу позвонить /sbin/reboot, так как он чистый мягкий сброс.

Спасибо за ваше время.

ответ

5

Просто идея: вы можете начать поток ядра по kthread_run(), положить его спать wait_event(), разбудить его в обработчик IRQ по wake_up(), делать вещи (запустить /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); 
} 

Не забудьте обработать модуль __exit и случай, когда прерывание пришло перед тем нить ядра была послана спать.

+0

Я исправил его так же :) https://github.com/moul/junk/blob/master/kernel/irq_reboot.c – moul

Смежные вопросы