Driver:
1 #include <linux/module.h> 2 #include <linux/fs.h> 3 #include <linux/mm.h> 4 #include <linux/init.h> 5 #include <linux/cdev.h> 6 #include <linux/slab.h> 7 #include <linux/uaccess.h> 8 9 #define SECOND_MAJOR 248 10 11 static int second_major = SECOND_MAJOR; 12 module_param(second_major, int, S_IRUGO); 13 14 struct second_dev { 15 struct cdev cdev; 16 atomic_t counter; 17 struct timer_list s_timer; 18 }; 19 20 static struct second_dev *second_devp; 21 22 static void second_timer_handler(unsigned long arg) 23 { 24 mod_timer(&second_devp->s_timer, jiffies + HZ); /* 触发下一次定时 */ 25 atomic_inc(&second_devp->counter); /* 增加秒计数 */ 26 27 printk(KERN_INFO "current jiffies is %ld\n", jiffies); 28 } 29 30 static int second_open(struct inode *inode, struct file *filp) 31 { 32 init_timer(&second_devp->s_timer); 33 second_devp->s_timer.function = &second_timer_handler; 34 second_devp->s_timer.expires = jiffies + HZ; 35 36 add_timer(&second_devp->s_timer); 37 38 atomic_set(&second_devp->counter, 0); /* 初始化秒计数为0 */ 39 40 return 0; 41 } 42 43 static int second_release(struct inode *inode, struct file *filp) 44 { 45 del_timer(&second_devp->s_timer); 46 47 return 0; 48 } 49 50 static ssize_t second_read(struct file *filp, char __user * buf, size_t count, 51 loff_t * ppos) 52 { 53 int counter; 54 55 counter = atomic_read(&second_devp->counter); 56 if (put_user(counter, (int *)buf)) /* 拷贝counter到userspace */ 57 return -EFAULT; 58 else 59 return sizeof(unsigned int); 60 } 61 62 static const struct file_operations second_fops = { 63 .owner = THIS_MODULE, 64 .open = second_open, 65 .release = second_release, 66 .read = second_read, 67 }; 68 69 static void second_setup_cdev(struct second_dev *dev, int index) 70 { 71 int err, devno = MKDEV(second_major, index); 72 73 cdev_init(&dev->cdev, &second_fops); 74 dev->cdev.owner = THIS_MODULE; 75 err = cdev_add(&dev->cdev, devno, 1); 76 if (err) 77 printk(KERN_ERR "Failed to add second device\n"); 78 } 79 80 static int __init second_init(void) 81 { 82 int ret; 83 dev_t devno = MKDEV(second_major, 0); 84 85 if (second_major) 86 ret = register_chrdev_region(devno, 1, "second"); 87 else { 88 ret = alloc_chrdev_region(&devno, 0, 1, "second"); 89 second_major = MAJOR(devno); 90 } 91 if (ret < 0) 92 return ret; 93 94 second_devp = kzalloc(sizeof(*second_devp), GFP_KERNEL); 95 if (!second_devp) { 96 ret = -ENOMEM; 97 goto fail_malloc; 98 } 99 100 second_setup_cdev(second_devp, 0); 101 102 return 0; 103 104 fail_malloc: 105 unregister_chrdev_region(devno, 1); 106 return ret; 107 } 108 module_init(second_init); 109 110 static void __exit second_exit(void) 111 { 112 cdev_del(&second_devp->cdev); 113 kfree(second_devp); 114 unregister_chrdev_region(MKDEV(second_major, 0), 1); 115 } 116 module_exit(second_exit); 117 118 MODULE_AUTHOR("Barry Song <[email protected]>"); 119 MODULE_LICENSE("GPL v2");
TstCase:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <signal.h> 7 #include <sys/stat.h> 8 9 10 int main(int argc, char **argv){ 11 int fd; 12 13 int counter = 0; 14 int old_counter = 0; 15 16 fd = open("/dev/second", O_RDONLY); 17 18 if (fd != - 1) { 19 while (1) { 20 read(fd,&counter, sizeof(unsigned int)); 21 22 if(counter!=old_counter) { 23 printf("seconds after open /dev/second :%d\n",counter); 24 old_counter = counter; 25 } 26 } 27 } else { 28 printf("Device open failure\n"); 29 } 30 }
Makefile
KVERS = $(shell uname -r) # Kernel modules obj-m += second.o # Specify flags for the module compilation. #EXTRA_CFLAGS=-g -O0 build: kernel_modules user_test kernel_modules: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules user_test: gcc -o second_test second_test.c clean: make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean