Bonjour,
Je suis débutant dans l'écriture de module linux.
J'essaye de faire une interface d'échange entre kernel et userland qui soit bloquant pour le user tant que le kernel n'a pas la donnée de disponible.
Je reprends , j'ai donc ceci
static struct file_operations toto_fops = {
.owner = THIS_MODULE,
.read = toto_read,
.write = toto_write,
.open = toto_open,
.release = toto_release,
};
static ssize_t toto_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
....
wait_data()
copy_to_user(buf, (int *)videomemory + (int)*ppos, lus);
.....
}
Le problème est donc de faire le wait_data() . Je sais dans une autre portion du module quand cette donnée est prête mais ceci est indépendant de l'application qui a fait le open.
Je pense qu'il faut utiliser les spin_lock mais j'ai du mal a voir comment.
Je suis juste dans un cas un peu plus compliqué que les exemples données sur Internet et je me dit que la route est longue pour bien tout comprendre ;-)
# Synchro
Posté par David Decotigny (site web personnel) . Évalué à 2.
[^] # Re: Synchro
Posté par shal . Évalué à 1.
En effet, je viens de freezer ma machine en tentant une synchro a coup de mutex_lock ;-)
Le LDD3 j'avais vu mais c'est lourd de tout prendre d'un coup...
Quoique je viens de voir que dans le chapitre 6 (Advanced char driver) il y a un paragraphe sur blocking I/O qui semble correspondre à mon besoin.
Merci
[^] # Re: Synchro
Posté par Nicolas Boulay (site web personnel) . Évalué à 2.
Tu devrais faire une attente limité puis retourner une erreur si un flag n'est pas mis.
"La première sécurité est la liberté"
# Et la fonction est...
Posté par Benoît Monin . Évalué à 4.
wait_event_interruptible
.Il faut que tu déclares un
wake_queue_head
dans ton module. Dans la fonction toto_read, tu mets le processus appelant en attente avecwait_event_interruptible
. Et dans ton interruption, enfin là ou tu sais que tes données sont disponibles tu appelleswake_up_interruptible
pour réveiller le processus bloqué.Ces macros sont définies dans include/linux/wait.h dans les sources du noyau. Utiliser les versions interruptibles, ça permet de quitter le processus en attente d'un simple Ctrl-C plutôt que de devoir redémarrer la machine lorsque les choses tournent mal (IT qui n'arrive pas, défaut matériel...).
Je te conseille de passer une demi-journée voire une journée à lire le Linux Device Driver volume 3, ce n'est pas du temps perdu.
# Ca fonctionne
Posté par shal . Évalué à 2.
un module test1 reçoit de la donné depuis le userland , le copie dans un buffer d'un module test2 qui peut être lu par le userland. l'application bloque tant qu'il n'y pas de donné.
J'ai fait deux modules de type filesystem. Les deux ont chacun un buffer alloué par vmalloc (de même taille).
le module test2 dispose d'une méthode test2_memcpy() qui est déclaré dans un fichier .h
dans test1.c
static struct file_operations test1_ops= {
....
.write = test1_write,
...
};
static ssize_t test1_write(struct file *file, const char *buf, size_t
count, loff_t *ppos) {
.....
copy_from_user((int *)buffer1 + (int)*ppos, buf, ecrits);
...
if( test2_memcpy()(buffer1,buffer1_size) != 0)
{
printk(KERN_DEBUG "test2_memcpy failed\n");
}
......
}
Dans test2.c:
static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag = 0;
static struct file_operations test2_ops= {
....
.read = test2_read,
...
};
static ssize_t test2_read(struct file *file, char *buf, size_t count,
loff_t *ppos) {
...
wait_event_interruptible(wq, flag != 0);
flag = 0;
copy_to_user(buf, (int *)buffer2 + (int)*ppos, lus);
.....
};
int test2_memcpy(char *buf, size_t count)
{
buffer2 != memcpy(buffer2, buf, count);
flag = 1;
wake_up_interruptible(&wq);
return 0;
}
EXPORT_SYMBOL( test2_memcpy);
Et ca marche ;-)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.