Add basic and chardev modules

This commit is contained in:
Florian RICHER 2025-02-08 17:01:11 +01:00
commit e3c9144b8a
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
10 changed files with 298 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

16
.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
# Ignore dev env files
.direnv
.idea
# Ignore generated files
*.cmd
*.mod.c
# Ignore all .ko files
*.ko
# Ignore other compiled files and directories
*.o
*.mod
*.symvers
*.order

7
01_basic_module/Makefile Normal file
View file

@ -0,0 +1,7 @@
obj-m += test_module.o
all:
make -C $(LINUX_MODULES_FOLDER)/build M=$(PWD) modules
clean:
make -C $(LINUX_MODULES_FOLDER)/build M=$(PWD) clean

View file

@ -0,0 +1,20 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int __init basic_module_init(void) {
printk(KERN_INFO "Bonjour! Le module est chargé.\n");
return 0;
}
static void __exit basic_module_exit(void) {
printk(KERN_INFO "Au revoir! Le module est déchargé.\n");
}
module_init(basic_module_init);
module_exit(basic_module_exit);
MODULE_LICENSE("MIT License");
MODULE_AUTHOR("Florian RICHER");
MODULE_DESCRIPTION("Un module noyau qui affiche un message");
MODULE_VERSION("1.0");

View file

@ -0,0 +1,7 @@
obj-m += test_module.o
all:
make -C $(LINUX_MODULES_FOLDER)/build M=$(PWD) modules
clean:
make -C $(LINUX_MODULES_FOLDER)/build M=$(PWD) clean

View file

@ -0,0 +1,31 @@
## Additionnal informations
To test character device, your need create the device.
Step 1: Get major number of your module device
```bash
cat /proc/devices | grep flodev
```
Step 2: Create device (as root)
```bash
mknod /dev/[wanted name] -c <major_number> 0
```
Exemple (as root):
```bash
cat /proc/devices | grep flodev # => 236 flodev
mknod /dev/flodev0 c 236 0
echo "Salut" >> /dev/flodev0
dmesg | tail # =>
# flodev - Ouverture du périphérique
# flodev - Message reçu: Salut
# flodev - Fermeture du périphérique
rm /dev/flodev0
```

View file

@ -0,0 +1,83 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "flodev"
#define CLASS_NAME "chardrv"
static int major_number;
static char msg[256] = {0};
static short size_of_msg;
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};
static int __init basic_module_init(void) {
printk(KERN_INFO "Bonjour! Le module est chargé.\n");
major_number = register_chrdev(0, DEVICE_NAME, &fops);
if (major_number < 0) {
printk(KERN_ALERT "Erreur lors de l'enregistrement du périphérique de caractère\n");
return major_number;
}
printk(KERN_INFO "Périphérique de caractère enregistré avec le numéro de majeur %d\n", major_number);
return 0;
}
static void __exit basic_module_exit(void) {
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_INFO "Au revoir! Le module est déchargé.\n");
}
static int device_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "flodev - Ouverture du périphérique\n");
return 0;
}
static int device_release(struct inode *inode, struct file *file) {
printk(KERN_INFO "flodev - Fermeture du périphérique\n");
return 0;
}
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset) {
int bytes_read = 0;
if (*offset >= size_of_msg) {
return 0;
}
if (*offset + length > size_of_msg) {
length = size_of_msg - *offset;
}
if (copy_to_user(buffer, msg + *offset, length)) {
return -EFAULT;
}
*offset += length;
bytes_read = length;
printk(KERN_INFO "flodev - Lecture de %d bytes\n", bytes_read);
return bytes_read;
}
static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t *off) {
if (copy_from_user(msg, buff, len)) {
return -EFAULT;
}
size_of_msg = len;
printk(KERN_INFO "flodev - Message reçu: %s\n", msg);
return len;
}
module_init(basic_module_init);
module_exit(basic_module_exit);
MODULE_LICENSE("MIT License");
MODULE_AUTHOR("Florian RICHER");
MODULE_DESCRIPTION("Un module noyau avec un périphérique de caractère");
MODULE_VERSION("1.0");

41
README.md Normal file
View file

@ -0,0 +1,41 @@
## Setup env
On NixOS:
- Ensure Linux Kernel is the same as you configuration.
Otherwise, change linux_dev variable with you kernel variant and change flake.lock nixpkgs with your version.
- Use direnv allow or nix develop to setup shell.
On other distros:
- You need to setup LINUX_MODULES_FOLDER to linux modules folder of your distro (ex: `/lib/modules/$(uname -r)/build`) in flake.nix
## make : targets list
- all : Compiling kernel
- clean : Cleaning build folder
All subfolder is configured to use LINUX_MODULES_FOLDER env variable set by flake develop
## How test module
Step 1: Load module
```bash
sudo insmod [module_name].ko
```
**Warning**: Can fail if secure boot is enabled
Step 2: Check logs
```bash
sudo dmesg | tail
```
Step 3: Unload module
```bash
sudo rmmod [module_name].ko
```

60
flake.lock generated Normal file
View file

@ -0,0 +1,60 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1739024019,
"narHash": "sha256-xvTo0Aw0+veek7hvEVLzErmJyQkEcRk6PSR4zsRQFEc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3a228057f5b619feb3186e986dbe76278d707b6e",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

32
flake.nix Normal file
View file

@ -0,0 +1,32 @@
{
description = "Environnement de développement pour des modules noyaux Linux";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
nixpkgs,
flake-utils,
...
}: flake-utils.lib.eachSystem flake-utils.lib.allSystems (system:
let
pkgs = import nixpkgs { inherit system; };
linux_dev = pkgs.linuxKernel.kernels.linux_zen.dev;
in {
devShells = {
default = pkgs.mkShell {
packages = [ linux_dev ];
LINUX_MODULES_FOLDER = "${linux_dev}/lib/modules/${linux_dev.modDirVersion}";
shellHook = ''
echo "Current Linux Kernel used : ${linux_dev.version}"
'';
};
};
}
);
}