#include <linux/module.h> #include <linux/hrtimer.h> #include <linux/ktime.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/slab.h> #include <linux/uaccess.h>
#define DEVICE_NAME "my_hrtimer_device" #define CLASS_NAME "my_hrtimer_class" #define IOCTL_SET_PID _IOW('f', 1, pid_t*)
static struct hrtimer my_hrtimer; static ktime_t kt_periode; static struct class* my_hrtimer_class = NULL; static struct device* my_hrtimer_device = NULL; static dev_t dev_num; static struct cdev my_cdev; static pid_t user_pid = -1; static struct task_struct *user_task = NULL;
enum hrtimer_restart my_hrtimer_callback(struct hrtimer *timer) { if (user_task) { send_sig_info(SIGUSR1, SEND_SIG_PRIV, user_task); }
hrtimer_forward_now(timer, kt_periode); return HRTIMER_RESTART; }
static long my_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case IOCTL_SET_PID: if (copy_from_user(&user_pid, (pid_t __user *)arg, sizeof(user_pid))) { return -EFAULT; } user_task = pid_task(find_vpid(user_pid), PIDTYPE_PID); if (!user_task) { return -ESRCH; } printk(KERN_INFO "Received PID: %d\n", user_pid); break; default: return -ENOTTY; } return 0; }
static struct file_operations fops = { .unlocked_ioctl = my_ioctl, };
static int __init my_hrtimer_init(void) { int ret;
printk(KERN_INFO "Initializing hrtimer module.\n");
ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); if (ret < 0) { printk(KERN_ERR "Failed to allocate char device region\n"); return ret; }
cdev_init(&my_cdev, &fops); ret = cdev_add(&my_cdev, dev_num, 1); if (ret < 0) { unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to add char device\n"); return ret; }
my_hrtimer_class = class_create(CLASS_NAME); if (IS_ERR(my_hrtimer_class)) { cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to create class\n"); return PTR_ERR(my_hrtimer_class); }
my_hrtimer_device = device_create(my_hrtimer_class, NULL, dev_num, NULL, DEVICE_NAME); if (IS_ERR(my_hrtimer_device)) { class_destroy(my_hrtimer_class); cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to create device\n"); return PTR_ERR(my_hrtimer_device); }
kt_periode = ktime_set(0, 1000000000);
hrtimer_init(&my_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); my_hrtimer.function = my_hrtimer_callback;
hrtimer_start(&my_hrtimer, kt_periode, HRTIMER_MODE_REL);
return 0; }
static void __exit my_hrtimer_exit(void) { int ret;
ret = hrtimer_cancel(&my_hrtimer); if (ret) { printk(KERN_INFO "Timer was still in use.\n"); }
device_destroy(my_hrtimer_class, dev_num); class_destroy(my_hrtimer_class); cdev_del(&my_cdev); unregister_chrdev_region(dev_num, 1);
printk(KERN_INFO "Exiting hrtimer module.\n"); }
module_init(my_hrtimer_init); module_exit(my_hrtimer_exit);
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Frank"); MODULE_DESCRIPTION("A simple hrtimer example module with signal to wake up user process");
|