eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: eleni@0: #define DEV_NAME "ktest" eleni@0: eleni@0: static int ktest_init(void); eleni@0: static void ktest_fini(void); eleni@0: eleni@0: static int ktest_open(struct inode *inode, struct file *file); eleni@0: static int ktest_release(struct inode *inode, struct file *file); eleni@0: static ssize_t ktest_read(struct file *file, char *buf, size_t buf_size, eleni@0: loff_t *offset); eleni@0: eleni@0: static int dev_num; eleni@0: static struct file_operations ops = { eleni@0: .open = ktest_open, eleni@0: .release = ktest_release, eleni@0: .read = ktest_read eleni@0: }; eleni@0: static int hello_counter; eleni@0: eleni@0: /* macros */ eleni@0: eleni@0: MODULE_LICENSE("GPL"); eleni@0: MODULE_AUTHOR("hikiko"); eleni@0: MODULE_DESCRIPTION("my kernel helloworld"); eleni@0: eleni@0: module_init(ktest_init); eleni@0: module_exit(ktest_fini); eleni@0: eleni@0: static int ktest_init(void) eleni@0: { eleni@0: hello_counter = 0; eleni@0: eleni@0: /* register character device */ eleni@0: if((dev_num = register_chrdev(0, DEV_NAME, &ops)) < 0) { eleni@0: printk(KERN_ALERT "Failed to register character device.\n"); eleni@0: return -1; eleni@0: } eleni@0: printk(KERN_INFO "Registered character device. Name: %s number: %d.\n", DEV_NAME, dev_num); eleni@0: return 0; eleni@0: } eleni@0: eleni@0: static void ktest_fini(void) eleni@0: { eleni@0: unregister_chrdev(dev_num, DEV_NAME); eleni@0: printk(KERN_INFO "Unregistered character device. Name: %s number: %d.\n", DEV_NAME, dev_num); eleni@0: } eleni@0: eleni@0: static int ktest_open(struct inode *inode, struct file *file) eleni@0: { eleni@0: /* 1 device file only => we ignore the params ^ */ eleni@0: try_module_get(THIS_MODULE); eleni@0: return 0; eleni@0: } eleni@0: eleni@0: static int ktest_release(struct inode *inode, struct file *file) eleni@0: { eleni@0: module_put(THIS_MODULE); eleni@0: return 0; eleni@0: } eleni@0: eleni@0: static ssize_t ktest_read(struct file *file, char *buf, size_t buf_size, eleni@0: loff_t *offset) eleni@0: { eleni@0: /* buf = userspace buffer, eleni@0: * kbuf = kernel buffer */ eleni@0: eleni@0: char *kbuf; eleni@0: int bytes; eleni@0: eleni@0: if(!(kbuf = kmalloc(buf_size, GFP_KERNEL))) { eleni@0: printk(KERN_ALERT "Failed to allocate memory.\n"); eleni@0: return -ENOMEM; eleni@0: } eleni@0: eleni@0: /* fill kbuf and copy to userspace buf */ eleni@0: bytes = snprintf(kbuf, buf_size, "Hello world, num: %d.\n", ++hello_counter); eleni@0: eleni@0: if(copy_to_user(buf, kbuf, bytes)) eleni@0: { eleni@0: kfree(kbuf); eleni@0: return -EFAULT; eleni@0: } eleni@0: eleni@0: kfree(kbuf); eleni@0: return bytes; eleni@0: }