From dab04d185218a556a2558646e9750ac40d8563d2 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Sun, 6 Aug 2017 12:21:05 +0100 Subject: [PATCH] character_device_create --- kernel_module/README.md | 1 + kernel_module/character_device.c | 31 +++++------- kernel_module/character_device_create.c | 61 +++++++++++++++++++++++ kernel_module/seq_file_single.c | 2 +- rootfs_overlay/character_device.sh | 4 +- rootfs_overlay/character_device_create.sh | 7 +++ 6 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 kernel_module/character_device_create.c create mode 100755 rootfs_overlay/character_device_create.sh diff --git a/kernel_module/README.md b/kernel_module/README.md index 892ea3e..1e6e716 100644 --- a/kernel_module/README.md +++ b/kernel_module/README.md @@ -31,6 +31,7 @@ 1. [dep](dep.c) 1. [dep2](dep2.c) 1. [character_device](character_device.c) + 1. [character_device_create](character_device_create.c) 1. [virt_to_phys](virt_to_phys.c) 1. Hardware device drivers 1. [pci_min](pci_min.c) diff --git a/kernel_module/character_device.c b/kernel_module/character_device.c index b89c2ca..a3d5f93 100644 --- a/kernel_module/character_device.c +++ b/kernel_module/character_device.c @@ -19,38 +19,31 @@ and use that for the mknod. - https://unix.stackexchange.com/questions/37829/understanding-character-device-or-character-special-files/371758#371758 */ -#include /* copy_from_user, copy_to_user */ -#include /* EFAULT */ #include /* register_chrdev, unregister_chrdev */ -#include #include -#include /* printk */ -#include /* S_IRUSR */ +#include /* seq_read, seq_lseek, single_release */ #define NAME "lkmc_character_device" static int major; -static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off) +static int show(struct seq_file *m, void *v) { - size_t ret; - char kbuf[] = {'a', 'b', 'c', 'd'}; + seq_printf(m, "abcd"); + return 0; +} - ret = 0; - if (*off == 0) { - if (copy_to_user(buf, kbuf, sizeof(kbuf))) { - ret = -EFAULT; - } else { - ret = sizeof(kbuf); - *off = 1; - } - } - return ret; +static int open(struct inode *inode, struct file *file) +{ + return single_open(file, show, NULL); } static const struct file_operations fops = { + .llseek = seq_lseek, + .open = open, .owner = THIS_MODULE, - .read = read, + .read = seq_read, + .release = single_release, }; static int myinit(void) diff --git a/kernel_module/character_device_create.c b/kernel_module/character_device_create.c new file mode 100644 index 0000000..d4ea30d --- /dev/null +++ b/kernel_module/character_device_create.c @@ -0,0 +1,61 @@ +/* +Automatically create the device under /dev on insmod, and remove on rmmod. + +https://stackoverflow.com/questions/5970595/create-a-device-node-in-code/ +https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module-code-of-a-linux-kernel-module/18594761#18594761 +*/ + +#include +#include +#include /* register_chrdev, unregister_chrdev */ +#include +#include /* seq_read, seq_lseek, single_release */ + +#define NAME "lkmc_character_device_create" + +static int major = -1; +static struct cdev mycdev; +static struct class *myclass = NULL; + +static int show(struct seq_file *m, void *v) +{ + seq_printf(m, "abcd"); + return 0; +} + +static int open(struct inode *inode, struct file *file) +{ + return single_open(file, show, NULL); +} + +static const struct file_operations fops = { + .llseek = seq_lseek, + .open = open, + .owner = THIS_MODULE, + .read = seq_read, + .release = single_release, +}; + +static int myinit(void) +{ + /* cat /proc/devices */ + alloc_chrdev_region(&major, 0, 1, NAME "_proc"); + /* ls /sys/class */ + myclass = class_create(THIS_MODULE, NAME "_sys"); + /* ls /dev/ */ + device_create(myclass, NULL, major, NULL, NAME "_dev"); + cdev_init(&mycdev, &fops); + cdev_add(&mycdev, major, 1); + return 0; +} + +static void myexit(void) +{ + device_destroy(myclass, major); + class_destroy(myclass); + unregister_chrdev_region(major, 1); +} + +module_init(myinit) +module_exit(myexit) +MODULE_LICENSE("GPL"); diff --git a/kernel_module/seq_file_single.c b/kernel_module/seq_file_single.c index b7eb9e7..a4205b4 100644 --- a/kernel_module/seq_file_single.c +++ b/kernel_module/seq_file_single.c @@ -25,7 +25,7 @@ static int show(struct seq_file *m, void *v) return 0; } -static int open(struct inode *inode, struct file *file) +static int open(struct inode *inode, struct file *file) { return single_open(file, show, NULL); } diff --git a/rootfs_overlay/character_device.sh b/rootfs_overlay/character_device.sh index e57dc57..89b3e8b 100755 --- a/rootfs_overlay/character_device.sh +++ b/rootfs_overlay/character_device.sh @@ -1,7 +1,7 @@ #!/bin/sh +set -ex insmod /character_device.ko /mknoddev.sh lkmc_character_device -cat /dev/lkmc_character_device -# => abcd +[ "$(cat /dev/lkmc_character_device)" = 'abcd' ] rm /dev/lkmc_character_device rmmod character_device diff --git a/rootfs_overlay/character_device_create.sh b/rootfs_overlay/character_device_create.sh new file mode 100755 index 0000000..5cc8354 --- /dev/null +++ b/rootfs_overlay/character_device_create.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -ex +insmod /character_device_create.ko +dev='/dev/lkmc_character_device_create_dev' +[ "$(cat "$dev")" = 'abcd' ] +rmmod character_device_create +[ ! -e "$dev" ]