1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| #include <linux/module.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/stat.h> #include <linux/init.h> #include <linux/device.h> #include <linux/tty.h> #include <linux/kmod.h> #include <linux/gfp.h> #include <asm/pgtable.h> #include <linux/mm.h> #include <linux/slab.h>
static int major = 0; static char *kernel_buf; static struct class *hello_class; static int bufsiz = 1024*8;
#define MIN(a, b) (a < b ? a : b)
static ssize_t hello_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset){ int err; err = copy_to_user(buf, kernel_buf, MIN(bufsiz, size)); return MIN(bufsiz, size); } static ssize_t hello_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset) { int err; err = copy_from_user(kernel_buf, buf, MIN(1024, size)); return MIN(1024, size); } static int hello_drv_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long phy = virt_to_phys(kernel_buf); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); if (remap_pfn_range(vma, vma->vm_start, phy >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { printk("mmap remap_pfn_range failed\n"); return -ENOBUFS; } return 0; }
static int hello_drv_open (struct inode *node, struct file *file){ return 0; } static int hello_drv_close (struct inode *node, struct file *file){ return 0; } static struct file_operations hello_drv = { .owner = THIS_MODULE, .open = hello_drv_open, .read = hello_drv_read, .write = hello_drv_write, .release = hello_drv_close, .mmap = hello_drv_mmap, };
static int __init hello_init(void) { int err; kernel_buf = kmalloc(bufsiz, GFP_KERNEL); strcpy(kernel_buf, "old"); major = register_chrdev(0, "hello", &hello_drv); hello_class = class_create(THIS_MODULE, "hello_class"); err = PTR_ERR(hello_class); if (IS_ERR(hello_class)) { printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__); unregister_chrdev(major, "hello"); return -1; } device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello"); return 0; }
static void __exit hello_exit(void) { device_destroy(hello_class, MKDEV(major, 0)); class_destroy(hello_class); unregister_chrdev(major, "hello"); kfree(kernel_buf); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
|