diff --git a/README.md b/README.md index 15506e1..98db27b 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/task_09/Makefile b/task_09/Makefile new file mode 100644 index 0000000..4817f3a --- /dev/null +++ b/task_09/Makefile @@ -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 diff --git a/task_09/sysfs.c b/task_09/sysfs.c new file mode 100644 index 0000000..fa1ebd3 --- /dev/null +++ b/task_09/sysfs.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define DEBUG 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +#include +#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 "); +MODULE_DESCRIPTION("Module pour tester le sysfs.");