2018年2月13日 星期二

Linux kernel - 創建一個無窮的timer

#include <linux/module.h>
#include <linux/init.h>

#include <linux/uaccess.h>
#include <linux/proc_fs.h>

#define TIMEOUT_FREQ(timer) ((HZ * timer) / 1000)

#define PROCNAME "timer"

MODULE_LICENSE("Dual BSD/GPL");

static struct timer_list tickfn;
static unsigned int timer1 = 1000;

static void sample_timeout(unsigned long arg)
{
 struct timer_list *tick = (struct timer_list *) arg;
 int ret;
 
 ret = mod_timer(tick, jiffies + TIMEOUT_FREQ(timer1));

 printk(KERN_INFO "mod_timer: %d (%lu)\n", ret, jiffies);
}

static int sample_proc_read(char *buf, char **start, off_t offset,
  int count, int *eof, void *data)
{
 char *p = buf;
 p += sprintf(p, "timer1 = %d (ms)\n", timer1);
 *eof = 1;
 
 if ((p - buf) > PAGE_SIZE)
  return -ENOBUFS;

 return p - buf;
}

static int sample_proc_write(struct file *file, const char *buffer,
  unsigned long count, void *data)
{
 char buf[16];
 char *ptr = (char *) buf;

 if (count > sizeof(buf))
  return -EINVAL;
 if (copy_from_user(buf, buffer, count))
  return -EFAULT;

 while (*ptr && (*ptr == ' ' || *ptr == '\t')) ptr++;
 timer1 = simple_strtoul(ptr, &ptr, 10);

 mod_timer(&tickfn, jiffies + TIMEOUT_FREQ(timer1));
 return count;
}

static void sample_init_timer(void)
{
 init_timer(&tickfn);
 tickfn.function = sample_timeout;
 tickfn.data = (unsigned long) &tickfn;
 tickfn.expires = jiffies + TIMEOUT_FREQ(timer1);
 add_timer(&tickfn);
}

static void sample_exit_timer(void)
{
 int ret;
 ret = del_timer(&tickfn);
}

static int sample_init_proc(void)
{
 struct proc_dir_entry *entry;

 entry = create_proc_entry(PROCNAME, 0666, NULL);

 if (entry == NULL) {
  printk(KERN_WARNING "sample: unable to create proc entry\n");
  return -ENOMEM;
 }

 entry->read_proc = (read_proc_t *) sample_proc_read;
 entry->write_proc = (write_proc_t *) sample_proc_write;

 return 0;
}

static void sample_exit_proc(void)
{
 remove_proc_entry(PROCNAME, NULL);
}

static int __init sample_init(void)
{
 sample_init_proc();
 sample_init_timer();

 printk(KERN_INFO "driver loaded\n");

 return 0;
}

static void __exit sample_exit(void)
{
 int ret = 0;
 sample_exit_proc();
 sample_exit_timer();

 printk(KERN_INFO "driver unloaded (%d)\n", ret);
}

module_init(sample_init);
module_exit(sample_exit);

沒有留言:

張貼留言