内核模块定期调用用户空间程序

时间:2016-02-18 11:24:48

标签: c++ linux linux-kernel insmod

我想定期从内核模块调用一个用户空间程序。但是当我尝试加载它时,内核程序正在冻结系统。  以下是该计划,

#include <linux/module.h>   /* Needed by all modules */
#include <linux/kernel.h>   /* Needed for KERN_INFO */
#include <linux/init.h>     /* Needed for the macros */
#include <linux/jiffies.h>
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/delay.h>

#define TIME_PERIOD 50000

static struct hrtimer hr_timer;
static ktime_t ktime_period_ns;

static enum hrtimer_restart timer_callback(struct hrtimer *timer){
    char userprog[] = "test.sh";
    char *argv[] = {userprog, "2", NULL };
    char *envp[] = {"HOME=/", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
printk("\n Timer is running");
hrtimer_forward_now(&hr_timer, ktime_period_ns);

printk("callmodule: %s\n", userprog);
call_usermodehelper(userprog, argv, envp, UMH_WAIT_PROC);
return HRTIMER_RESTART;
}

static int __init timer_init() {
    ktime_period_ns= ktime_set( 0, TIME_PERIOD);
    hrtimer_init ( &hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
    hr_timer.function = timer_callback;
    hrtimer_start( &hr_timer, ktime_period_ns, HRTIMER_MODE_REL );
    return 0;
}


static int __exit timer_exit(){

    int cancelled = hrtimer_cancel(&hr_timer);

    if (cancelled)
        printk(KERN_ERR "Timer is still running\n");
    else
        printk(KERN_ERR "Timer is cancelled\n");

}
module_init(timer_init);
module_exit(timer_exit);

MODULE_LICENSE("GPL");

test.sh是一个只回应评论的脚本。 我已经单独测试了call_usermodehelper部分和计时器部分,它工作正常。但是当我将这两个代码组合在一起时,系统就会挂起。 有人可以帮我解决问题。

1 个答案:

答案 0 :(得分:0)

快速浏览强烈建议hrtimer回调是从irq上下文执行的,这是预期的 - 你还有什么方法可以获得高分辨率?

但这也意味着你必须没有阻止,而你的回调可能因call_usermodehelper而阻塞,而不管NOWAIT是否通过。

所以看起来你在调试禁用的内核上测试你的模块,这是根本错误的。

但这并不那么重要,因为你首先想要实现的东西看起来根本就错了。

我只能建议你详细说明实际问题是什么。现在绝对存在这样的方式:分叉+执行与需要高分辨率计时器的事情有关。