add task 9

This commit is contained in:
rick 2024-01-23 20:08:20 +01:00
parent 3d9046f06d
commit 050fe309f9
Signed by: Rick
GPG key ID: 5CBE8779CD27BCBA
3 changed files with 250 additions and 0 deletions

View file

@ -230,6 +230,58 @@ ls -l /sys/kernel/debug/eudyptula/
* [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)
### Tache 9
Idem que la tache 8 pour tester les sémaphores.
```bash
ls -l /sys/eudyptula/
# total 0
# -rw-r--r-- 1 root root 4096 Jan 23 18:42 foo
# -rw-rw-rw- 1 root root 4096 Jan 23 18:42 id
# -r--r--r-- 1 root root 4096 Jan 23 18:42 jiffies
echo pouet > /sys/eudyptula/foo
cat /sys/eudyptula/foo
# pouet
echo coucou ! > /sys/eudyptula/foo
cat /sys/eudyptula/foo
# coucou !
cat /sys/eudyptula/id
# pouetpouet
echo -n congruent > /sys/eudyptula/id
echo $?
# 0
echo pouet > /sys/eudyptula/id
# bash: echo: write error: Invalid argument
echo $?
# 1
echo pouet > /sys/eudyptula/jiffies
# bash: /sys/eudyptula/jiffies: Permission denied
cat /sys/eudyptula/jiffies
# 4344413015
cat /sys/eudyptula/jiffies
# 4344413465
echo pouet > /sys/eudyptula/foo &
cat /sys/eudyptula/foo
# cat: /sys/eudyptula/foo: Invalid argument
cat /sys/eudyptula/foo &
cat /sys/eudyptula/foo &
echo pouet > /sys/eudyptula/foo
# bash: echo: write error: Invalid argument
rmmod sysfs
ls -l /sys/eudyptula/
# ls: cannot access '/sys/eudyptula/': No such file or directory
```
* [The zen of kobjects](https://lwn.net/Articles/51437/) : un peu vieux, certaines fonctions pas
à jour
* [kobjects and sysfs](https://lwn.net/Articles/54651/) : idem
* [Everything you never wanted to know about kobjects, ksets, and
ktypes](https://docs.kernel.org/core-api/kobject.html) (documentation noyau)
* [Exemple de code pour
`kobject`](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/samples/kobject)
* [Chapitre 14, Linux Device Drivers, 3rd Edition](https://lwn.net/Kernel/LDD3/)
## Informations diverses
Je liste dans cette section quelques informations que j'ai pu découvrir en

9
task_09/Makefile Normal file
View file

@ -0,0 +1,9 @@
obj-m += sysfs.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

189
task_09/sysfs.c Normal file
View file

@ -0,0 +1,189 @@
// SPDX-License-Identifier: GPL-2.0
#define DEBUG 1
#include <asm/page.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#ifdef DEBUG
#include <linux/delay.h>
#endif
#define BUFFER_LENGTH 10
// représente un dossier sur sysfs
static struct kobject eudyptula;
// représente un fichier sur sysfs
static struct attribute id_file = {
.name = "id",
.mode = 0666
};
static struct attribute jiffies_file = {
.name = "jiffies",
.mode = 0444
};
static struct attribute foo_file = {
.name = "foo",
.mode = 0644
};
static char *id_msg;
static char *foo_msg;
static struct rw_semaphore foo_sem;
/*
* fonctions pour pouvoir lire et écrire dans les fichiers. elles sont ici
* découpées pour mieux se rendre compte. Il faut cependant les appeler depuis
* les fonctions se trouvant plus bas.
*/
static ssize_t id_read(char *buffer)
{
return sysfs_emit(buffer, id_msg);
}
static ssize_t id_write(const char *buffer, size_t size)
{
int ret = -EINVAL;
if (!strcmp(buffer, "congruent"))
ret = size;
return ret;
}
static ssize_t jiffies_read(char *buffer)
{
return sprintf(buffer, "%lld\n", jiffies_64);
}
static ssize_t foo_read(char *buffer)
{
int ret = -EINVAL;
if (down_read_trylock(&foo_sem)) {
ret = sysfs_emit(buffer, foo_msg);
#ifdef DEBUG
msleep(5000);
#endif
up_read(&foo_sem);
}
return ret;
}
static ssize_t foo_write(const char *buffer, size_t count)
{
int ret = -EINVAL;
if (down_write_trylock(&foo_sem)) {
ret = strscpy(foo_msg, buffer, count + 1);
#ifdef DEBUG
msleep(5000);
#endif
up_write(&foo_sem);
}
return ret;
}
/*
* fonctions utilisées pour lire et écrire dans les attributes. Elles sont
* mises dans une structure sysfs_ops et mis à l'initialisation du kobject via
* un ktype.
*/
ssize_t show(struct kobject *kobj, struct attribute *attr, char *buffer)
{
ssize_t ret = 0;
if (!strcmp(attr->name, "id"))
ret = id_read(buffer);
else if (!strcmp(attr->name, "jiffies"))
ret = jiffies_read(buffer);
else if (!strcmp(attr->name, "foo"))
ret = foo_read(buffer);
else
pr_info("keske tu essaies de lire ?!");
return ret;
}
ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buffer,
size_t len)
{
ssize_t ret = 0;
if (!strcmp(attr->name, "id"))
ret = id_write(buffer, len);
else if (!strcmp(attr->name, "foo"))
ret = foo_write(buffer, len);
else
pr_info("keske tu essaies d'ecrire ?!");
return ret;
}
static const struct sysfs_ops my_ops = {
.show = &show,
.store = &store,
};
static const struct kobj_type my_type = {
.sysfs_ops = &my_ops,
};
static int __init my_init(void)
{
pr_info("Coucou le gens !!!!\n");
if (!memset(&eudyptula, 0, sizeof(struct kobject)))
return -ENOMEM;
if (kobject_init_and_add(&eudyptula, &my_type, NULL, "eudyptula")) {
kobject_put(&eudyptula);
return -ENOMEM;
}
if (sysfs_create_file(&eudyptula, &id_file)
|| sysfs_create_file(&eudyptula, &jiffies_file)
|| sysfs_create_file(&eudyptula, &foo_file)) {
kobject_put(&eudyptula);
return -ENOMEM;
}
init_rwsem(&foo_sem);
id_msg = kmalloc(12, GFP_KERNEL);
foo_msg = kmalloc(PAGE_SIZE, GFP_KERNEL);
strscpy(id_msg, "pouetpouet\n", 12);
return 0;
}
static void __exit my_exit(void)
{
sysfs_remove_file(&eudyptula, &id_file);
sysfs_remove_file(&eudyptula, &jiffies_file);
sysfs_remove_file(&eudyptula, &foo_file);
kobject_put(&eudyptula);
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 sysfs.");