aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2024-04-18 15:23:17 +0200
committerlonkaars <loek@pipeframe.xyz>2024-04-18 15:23:17 +0200
commitc83f52365564e70450841b632547f4563920b1fb (patch)
treeeb126f11c1f333860a26f7a60193fdf380225cba
parent040e04244229fa0f7af4c15f3d9c4d11e1253996 (diff)
add character driver fops struct + implementation
-rw-r--r--1/Makefile5
-rw-r--r--1/fopdrv.c28
-rw-r--r--1/fopdrv.h11
-rw-r--r--1/main.c13
-rw-r--r--readme.md27
5 files changed, 81 insertions, 3 deletions
diff --git a/1/Makefile b/1/Makefile
index a345845..d968e31 100644
--- a/1/Makefile
+++ b/1/Makefile
@@ -3,8 +3,11 @@ KERNEL := /lib/modules/$(RELEASE)/build
# PWD doesn't have to be defined as it's inherited from the current environment
# MAKE shouldn't be defined as it's special in GNU make
+# the names of these variables are required by the kernel's (imo weird) build
+# system, see [kbuild-obj-var] and [kbuild-module-makefile] in ../readme.md
obj-m += lork.o
-lork-y := main.o
+lork-y += main.o
+lork-y += fopdrv.o
all:
$(MAKE) -C $(KERNEL) M=$(PWD) modules
diff --git a/1/fopdrv.c b/1/fopdrv.c
new file mode 100644
index 0000000..31c76cd
--- /dev/null
+++ b/1/fopdrv.c
@@ -0,0 +1,28 @@
+#include "fopdrv.h"
+
+// driver/char/mem.c read_null (/dev/null)
+ssize_t fop_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
+ return 0;
+}
+
+// driver/char/mem.c write_null
+ssize_t fop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
+ return count;
+}
+
+int fop_open(struct inode * inode, struct file * file) {
+ printk("%s\n", __PRETTY_FUNCTION__);
+ return 0;
+ // 0 seems to be a safe return value as it's used in driver/char/mem.c. The
+ // manual page for open(2) says that the system call returns a nonnegative
+ // integer representing the file descriptor on success, but it does not
+ // appears to be required.
+}
+
+int fop_release(struct inode * inode, struct file * file) {
+ printk("%s\n", __PRETTY_FUNCTION__);
+ return 0;
+ // same as above, but found in driver/char/lp.c
+}
+
+
diff --git a/1/fopdrv.h b/1/fopdrv.h
new file mode 100644
index 0000000..f2ca18c
--- /dev/null
+++ b/1/fopdrv.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+// declarations copied from linux/fs.h
+ssize_t fop_read(struct file *, char __user *, size_t, loff_t *);
+ssize_t fop_write(struct file *, const char __user *, size_t, loff_t *);
+int fop_open(struct inode *, struct file *);
+int fop_release(struct inode *, struct file *);
+
diff --git a/1/main.c b/1/main.c
index 7299f36..88ae0d0 100644
--- a/1/main.c
+++ b/1/main.c
@@ -1,15 +1,24 @@
#include <linux/init.h>
#include <linux/module.h>
+#include "fopdrv.h"
+
MODULE_LICENSE("MIT");
+struct file_operations fops = {
+ .read = fop_read,
+ .write = fop_write,
+ .open = fop_open,
+ .release = fop_release,
+};
+
static int mod_init(void) {
- printk(KERN_ALERT "Hello, world\n");
+ printk("%s\n", __PRETTY_FUNCTION__);
return 0;
}
static void mod_exit(void) {
- printk(KERN_ALERT "Goodbye, world\n");
+ printk("%s\n", __PRETTY_FUNCTION__);
}
module_init(mod_init);
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..f8f735d
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,27 @@
+# sources
+
+- [Kbuild object variable name rationale][kbuild-obj-var]
+- [Kbuild kernel module setup guide][kbuild-module-makefile]
+- [`struct file_operations`][c-struct-file-operations] documentation, also
+ - write(2)
+ - read(2)
+- (Sadly) [the Linux kernel source][kernel] itself, especially
+ - drivers/char/random.c
+ - drivers/char/mem.c
+
+[kbuild-obj-var]: https://docs.kernel.org/kbuild/makefiles.html#loadable-module-goals-obj-m
+[kbuild-module-makefile]: https://www.kernel.org/doc/html/latest/kbuild/modules.html#creating-a-kbuild-file-for-an-external-module
+[c-struct-file-operations]: https://www.kernel.org/doc/html/latest/filesystems/vfs.html#struct-file-operations
+[kernel]: https://github.com/torvalds/linux
+
+# tips
+
+- When the kernel documentation references manpages, these actually contain
+ useful information. Manpages are not only for commands, but also include
+ detailed documentation for the syscall interface and other C APIs.
+
+ Since most of the manpages referenced by the kernel are from section 2 (on
+ system calls), you should append the number between brackets to the `man`
+ command, i.e. to read 'write(2)' use the command `man 2 write`.
+- Use `dmesg` with the `-w` or `-W` option (see man dmesg(1))
+