diff --git a/README.md b/README.md index d12666e..db8c9d5 100644 --- a/README.md +++ b/README.md @@ -342,3 +342,4 @@ But TODO I don't think you can see where you are in the kernel source code and l 1. Module dependencies 1. [dep.c](kernel_module/dep.c) 1. [dep2.c](kernel_module/dep2.c) + 1. [character_device](kernel_module/character_device.c) diff --git a/kernel_module/character_device.c b/kernel_module/character_device.c new file mode 100644 index 0000000..14b7448 --- /dev/null +++ b/kernel_module/character_device.c @@ -0,0 +1,67 @@ +/* +Allows us to create device files with given file operations with mknod c X. + +Usage: + + /character_device.sh + +The major number determines which module owns the device file. + +minor is to differentiate between multiple instances of the device, +e.g. two NVIDIA GPUs using the same kernel module. + +We ask the kernel to automatically allocate a major number for us to avoid +conlicts with other devices. + +Then we need to check /proc/devices to find out the assigned number, +and use that for the mknod. +*/ + +#include /* copy_from_user, copy_to_user */ +#include /* EFAULT */ +#include /* register_chrdev, unregister_chrdev */ +#include +#include +#include /* printk */ +#include /* S_IRUSR */ + +#define NAME "lkmc_character_device" + +MODULE_LICENSE("GPL"); + +static int major; + +static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off) +{ + size_t ret; + char kbuf[] = {'a', 'b', 'c', 'd'}; + + ret = 0; + if (*off == 0) { + if (copy_to_user(buf, kbuf, sizeof(kbuf))) { + ret = -EFAULT; + } else { + ret = sizeof(kbuf); + *off = 1; + } + } + return ret; +} + +static const struct file_operations fops = { + .read = read, +}; + +static int myinit(void) +{ + major = register_chrdev(0, NAME, &fops); + return 0; +} + +static void myexit(void) +{ + unregister_chrdev(major, NAME); +} + +module_init(myinit) +module_exit(myexit) diff --git a/rootfs_overlay/character_device.sh b/rootfs_overlay/character_device.sh new file mode 100755 index 0000000..8205855 --- /dev/null +++ b/rootfs_overlay/character_device.sh @@ -0,0 +1,7 @@ +#!/bin/sh +insmod /character_device.ko +major="$(grep lkmc_character_device /proc/devices | cut -d ' ' -f 1)" +mknod /character_device.dev c $major 0 +cat /character_device.dev +# => abcd +rmmod character_device