2

I want to call a user space program from a kernel module periodically.But the kernel program is freezing the system, while I try to load it. following is the program,

#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 is a script which just echoes a comment. I have tested the call_usermodehelper part and timer part individually and it is working fine. But while I am combining the two codes, the system hangs. Can anybody please help me to solve the problem.

BusyTraveller
  • 183
  • 3
  • 14
  • You are calling your timer every 50us, are you sure that is correct? Try with a one second or more period, to see that if it works. – HappyCactus Feb 18 '16 at 11:28
  • 1
    Callback for *hrtimer* is executed in *atomic* context, so it shouldn't block. `call_usermodehelper` blocks caller process until called program returns. You may use `delayed_work` instead of hrtimer for periodically execute blocking tasks. – Tsyvarev Feb 18 '16 at 11:41
  • Yes....call_usermodehelper is blocking the code. But test.sh is just echo "testing" . No idea, while it is not coming out of it. – BusyTraveller Feb 18 '16 at 11:46
  • Yes....call_usermodehelper is blocking the code. But test.sh is just echo "testing" . No idea, why it is not coming out of it – BusyTraveller Feb 18 '16 at 11:48
  • 1
    *Fast* != *atomic*. Moreover, "fast" from the view of user space is not "fast" from the view of the kernel. E.g., `just echo` means that you write into console file, and write itself may block. – Tsyvarev Feb 18 '16 at 19:43
  • After changing the time period to 5s or even 50s also, the system is getting hanged.I am afraid, we are missing something. – BusyTraveller Feb 19 '16 at 05:15
  • I have tried using add_timer() also. but same fate – BusyTraveller Feb 19 '16 at 06:40
  • I think there is some issue with call_usermodehelper(). I have posted the following thread.http://stackoverflow.com/questions/35500687 – BusyTraveller Feb 19 '16 at 08:35

1 Answers1

0

Quick look around strongly suggests that hrtimer callbacks are executed from an irq context, which is expected - how else are you going to get high resoluton?

But this also means you must no block, while your callback can block due to call_usermodehelper regardless of NOWAIT passed.

So it seems you are testing your module on a kernel with debugging disabled, which is fundamentally wrong.

But this is less relevant as the thing you are trying to achieve in the first place looks fundamentally wrong.

I can only recommend you elaborate what is the actual problem. There is absolutely now way that forking + execing has anything to do with something requiring a high resolution timer.

  • I will make my requirement very clear. I want the kernel module to periodically check whether a particular user process is running,and if it is not running just trigger it.The period can be 5 to 10 seconds.So a high resolution timer is not reeally required. But even while I had tried with the normal timer (linux/timer.h), the result is same. – BusyTraveller Feb 19 '16 at 17:18
  • What does 'trigger' mean and why would the kernel do this in the first place? Why can't you stick to userspace? As for the failure, given lack of debug information it is impossible to say what else could have happened. –  Feb 19 '16 at 18:41
  • Actually, it is an application specific requirement.I will try to get the debugging information. – BusyTraveller Feb 22 '16 at 05:28