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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/device.h>
#define DEVICE_NAME "hello" #define CLASS_NAME "hello"
static int major; static struct class *hello_class = NULL; static struct cdev hello_cdev;
static char msg[100] = {0}; static int msg_len = 0;
static int hello_open(struct inode *inode, struct file *file) { printk(KERN_INFO "Hello device opened\n"); return 0; }
static int hello_release(struct inode *inode, struct file *file) { printk(KERN_INFO "Hello device closed\n"); return 0; }
static ssize_t hello_read(struct file *filp, char __user *buf, size_t len, loff_t *off) { int retval = 0; if (*off > 0) return 0; if (copy_to_user(buf, msg, msg_len)) { retval = -EFAULT; goto out; } *off += msg_len; retval = msg_len; out: return retval; }
static ssize_t hello_write(struct file *filp, const char __user *buf, size_t len, loff_t *off) { if (len > sizeof(msg) - 1) return -EINVAL; if (copy_from_user(msg, buf, len)) return -EFAULT; msg_len = len; msg[msg_len] = '\0'; printk(KERN_INFO "Received %zu characters from user\n", len); return len; }
static struct file_operations hello_fops = { .owner = THIS_MODULE, .open = hello_open, .release = hello_release, .read = hello_read, .write = hello_write, };
static int __init hello_init(void) { dev_t dev = 0; int ret; ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); if (ret < 0) { printk(KERN_ERR "Failed to allocate char device region\n"); return ret; } major = MAJOR(dev); printk(KERN_INFO "Hello module loaded with major number %d\n", major); cdev_init(&hello_cdev, &hello_fops); hello_cdev.owner = THIS_MODULE; ret = cdev_add(&hello_cdev, dev, 1); if (ret < 0) { printk(KERN_ERR "Failed to add cdev\n"); unregister_chrdev_region(dev, 1); return ret; } hello_class = class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(hello_class)) { printk(KERN_ERR "Failed to create device class\n"); cdev_del(&hello_cdev); unregister_chrdev_region(dev, 1); return PTR_ERR(hello_class); } device_create(hello_class, NULL, dev, NULL, DEVICE_NAME); return 0; }
static void __exit hello_exit(void) { dev_t dev = MKDEV(major, 0); device_destroy(hello_class, dev); class_destroy(hello_class); cdev_del(&hello_cdev); unregister_chrdev_region(dev, 1); printk(KERN_INFO "Hello module unloaded\n"); }
module_init(hello_init); module_exit(hello_exit);
MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple Linux char driver"); MODULE_VERSION("0.1");
|