add task 8
This commit is contained in:
parent
e2836073c6
commit
1441afda58
3 changed files with 221 additions and 0 deletions
50
README.md
50
README.md
|
@ -180,6 +180,56 @@ echo "bonjour12" > /dev/eudyptula
|
|||
* [Linux Kernel Labs - Character device drivers](https://linux-kernel-labs.github.io/refs/heads/master/labs/device_drivers.html#read-and-write)
|
||||
* [Nihall - Misc character devices](https://nihaal.me/post/misc_char_devices/)
|
||||
|
||||
## Tache 8
|
||||
|
||||
L'ajout d'une nouvelle string dans le fichier ne supprime l'entièreté du
|
||||
contenu du fichier. J'ai testé les sémaphores avec des `msleep`
|
||||
(`<linux/delay.h>`) rajouté dans le code. Il est possible de tester en
|
||||
décommentant le premier `define`.
|
||||
|
||||
```bash
|
||||
ls -l /sys/kernel/debug/eudyptula/
|
||||
# total 0
|
||||
# -rw-rw-r-- 1 root root 0 Jan 9 22:46 foo
|
||||
# -rw-rw-rw- 1 root root 0 Jan 9 22:44 id
|
||||
# -r--r--r-- 1 root root 0 Jan 9 22:45 jiffies
|
||||
echo pouet > /sys/kernel/debug/eudyptula/foo
|
||||
cat /sys/kernel/debug/eudyptula/foo
|
||||
# pouet
|
||||
echo coucou ! > /sys/kernel/debug/eudyptula/foo
|
||||
cat /sys/kernel/debug/eudyptula/foo
|
||||
# coucou !
|
||||
cat /sys/kernel/debug/eudyptula/id
|
||||
# pouetpouet
|
||||
echo congruent > /sys/kernel/debug/eudyptula/id
|
||||
echo $?
|
||||
# 0
|
||||
echo pouet > /sys/kernel/debug/eudyptula/id
|
||||
# bash: echo: write error: Invalid argument
|
||||
echo $?
|
||||
# 1
|
||||
echo pouet > /sys/kernel/debug/eudyptula/jiffies
|
||||
# bash: echo: write error: Permission denied
|
||||
cat /sys/kernel/debug/eudyptula/jiffies
|
||||
# 4345895105
|
||||
cat /sys/kernel/debug/eudyptula/jiffies
|
||||
# 4345895338
|
||||
echo pouet > /sys/kernel/debug/eudyptula/foo &
|
||||
cat /sys/kernel/debug/eudyptula/foo
|
||||
# cat: /sys/kernel/debug/eudyptula/foo: Invalid argument
|
||||
cat /sys/kernel/debug/eudyptula/foo &
|
||||
cat /sys/kernel/debug/eudyptula/foo &
|
||||
echo pouet > /sys/kernel/debug/eudyptula/foo
|
||||
# bash: echo: write error: Invalid argument
|
||||
rmmod hello
|
||||
ls -l /sys/kernel/debug/eudyptula/
|
||||
# ls: cannot access '/sys/kernel/debug/eudyptula/': No such file or directory
|
||||
```
|
||||
|
||||
* [DebugFS (Documentation kernel)](https://docs.kernel.org/filesystems/debugfs.html)
|
||||
* [Chapitre 3, Linux Device Drivers, 3rd Edition](https://lwn.net/Kernel/LDD3/)
|
||||
* [Jiffies, Linux Kernel Development 2nd Edition](https://litux.nl/mirror/kerneldevelopment/0672327201/ch10lev1sec3.html)
|
||||
|
||||
## Informations diverses
|
||||
|
||||
Je liste dans cette section quelques informations que j'ai pu découvrir en
|
||||
|
|
9
task_08/Makefile
Normal file
9
task_08/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
obj-m += debugfs.o
|
||||
|
||||
PWD := $(CURDIR)
|
||||
|
||||
all:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
162
task_08/debugfs.c
Normal file
162
task_08/debugfs.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/rwsem.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <linux/kernel.h>
|
||||
#endif
|
||||
|
||||
#define BUFFER_LENGTH 10
|
||||
|
||||
static struct dentry *folder;
|
||||
static struct dentry *id_file;
|
||||
static struct dentry *foo_file;
|
||||
|
||||
static char *id_msg;
|
||||
static char *foo_msg;
|
||||
static struct rw_semaphore foo_sem;
|
||||
|
||||
static ssize_t id_read(struct file *, char __user *buffer, size_t length, loff_t *offset)
|
||||
{
|
||||
int bytes = 0;
|
||||
const char *msg_tmp = id_msg;
|
||||
|
||||
/*
|
||||
* TODO
|
||||
if (!*(msg_tmp + *offset)) {
|
||||
*offset = 0;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
msg_tmp += *offset;
|
||||
|
||||
while (*msg_tmp && bytes < length) {
|
||||
put_user(*(msg_tmp), (buffer + bytes));
|
||||
bytes++;
|
||||
msg_tmp++;
|
||||
}
|
||||
|
||||
*offset += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static ssize_t id_write(struct file *, const char __user *buffer,
|
||||
size_t size, loff_t *)
|
||||
{
|
||||
int ret;
|
||||
char *tmp_buffer;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
tmp_buffer = kzalloc(BUFFER_LENGTH, GFP_KERNEL);
|
||||
|
||||
if (copy_from_user(tmp_buffer, buffer, BUFFER_LENGTH)) {
|
||||
kfree(tmp_buffer);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*(tmp_buffer + BUFFER_LENGTH - 1) = '\0';
|
||||
pr_info("Test %s-\n", tmp_buffer);
|
||||
|
||||
if (!strcmp(tmp_buffer, "congruent"))
|
||||
ret = BUFFER_LENGTH;
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
kfree(tmp_buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations id_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = id_read,
|
||||
.write = id_write,
|
||||
};
|
||||
|
||||
static ssize_t foo_read(struct file *, char __user *buffer, size_t count, loff_t *offset)
|
||||
{
|
||||
int bytes = -EINVAL;
|
||||
int tmp_len = strlen(foo_msg);
|
||||
|
||||
if (*offset > tmp_len) bytes = -EFAULT;
|
||||
else if (down_read_trylock(&foo_sem))
|
||||
{
|
||||
char *tmp_str = foo_msg + *offset;
|
||||
tmp_len = strlen(tmp_str);
|
||||
|
||||
bytes = tmp_len > count ? count : tmp_len;
|
||||
if (copy_to_user(buffer, tmp_str, bytes)) bytes = -EFAULT;
|
||||
else *offset += bytes;
|
||||
#ifdef DEBUG
|
||||
msleep(5000);
|
||||
#endif
|
||||
up_read(&foo_sem);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static ssize_t foo_write(struct file *, const char __user *buffer,
|
||||
size_t count, loff_t * offset)
|
||||
{
|
||||
int bytes = -EINVAL;
|
||||
|
||||
if ((*offset + count) > PAGE_SIZE) bytes = -EFAULT;
|
||||
else if (down_write_trylock(&foo_sem))
|
||||
{
|
||||
bytes = count;
|
||||
if (copy_from_user(foo_msg, buffer, bytes)) bytes = -EINVAL;
|
||||
#ifdef DEBUG
|
||||
msleep(5000);
|
||||
#endif
|
||||
up_write(&foo_sem);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static const struct file_operations foo_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = foo_read,
|
||||
.write = foo_write,
|
||||
};
|
||||
|
||||
static int __init my_init(void)
|
||||
{
|
||||
init_rwsem(&foo_sem);
|
||||
id_msg = kmalloc(12, GFP_KERNEL);
|
||||
foo_msg = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
strcpy(id_msg, "pouetpouet\n");
|
||||
pr_info("Coucou le gens !!!!\n");
|
||||
|
||||
folder = debugfs_create_dir("eudyptula", NULL);
|
||||
id_file = debugfs_create_file("id", 0666, folder, NULL, &id_fops);
|
||||
debugfs_create_u64("jiffies", 0444, folder, &jiffies_64);
|
||||
foo_file = debugfs_create_file("foo", 0664, folder, NULL, &foo_fops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit my_exit(void)
|
||||
{
|
||||
debugfs_remove_recursive(folder);
|
||||
kfree(id_msg);
|
||||
kfree(foo_msg);
|
||||
pr_info("Tschuss !!!\n");
|
||||
}
|
||||
|
||||
module_init(my_init);
|
||||
module_exit(my_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("rick <rick@gnous.eu>");
|
||||
MODULE_DESCRIPTION("Module pour tester le debugfs.");
|
Loading…
Reference in a new issue