我需要在内核中处理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')
,因为它清理软复位。
感谢您的时间。
答案 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);
}
以及在内核线程被发送到休眠状态之前中断的情况。