#1 Le 27/03/2008, à 16:37
- rniamo
while(1), y a pas mieux ? [Si, y a mieux : Résolu]
bonjour, je développe une application pour récupérer les événements d'un volant/joystick. Mon code est largement basé sur celui des ff-utils mais une partie me gêne :
while(1)
{
read(fd,&js,sizeof(...));
etc...
}
(c'est pas le vrai code mais l'idée est là).
En gros on lit sans cesse le périphérique mais quand j'ai voulu mettre une interface gtk en place, ce "while(1)" bloque l'interface. Peut-on faire differemment ?
Le code est là : http://www.rniamo-developping.prog.fr/volant.tar.gz
Dernière modification par rniamo (Le 27/03/2008, à 22:03)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#2 Le 27/03/2008, à 16:53
- philou8237
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
oui.... traiter les interruptions. Lorsque ton volant émet des données vers ta machine, une interuption matérielle est levée par le processeur. (IRQ n°xx selon la configuration du PIC). Cela implique que ton bout de code tourne en mode kernel, comme pilote du noyau linux.
Tu ne pourras pas gérer proprement ton volant autrement. Faire un thread spécialement pour ça et faire tourner l'interface graph sur un autre thread.... c'est pabo !
Sinon, tu fais une partie en mode kernel, qui se fais exécuter lorsque l'IRQ correspondante est traitée par le noyau, et une partie en userland, qui reçoit les informations à partir de la partie en kernel land.
ps: si il existe déjà un pilote ds le noyau... c'est avec lui qu'il faut dialoguer, donc voir pour lui faire exécuter qque chose lorsqu'il reçoit des données, en utilisant les IPC/signaux par exemple.
Dernière modification par philou8237 (Le 27/03/2008, à 17:00)
Hors ligne
#3 Le 27/03/2008, à 17:08
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
tu peux développer stp ? le pilode est le pilote (usb)hid.
Est-ce portable (au niveau processeur) ?
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#4 Le 27/03/2008, à 17:13
- bipede
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
C'est dans la faq python-gtk, mais ça doit être équivalent pour le C...
http://faq.pygtk.org/index.py?req=show& … 03.007.htp
Desktop: MSI - Intel® Core™ i5-3330 CPU @ 3.00GHz × 4 - RAM 8 go- Kubuntu 21.04 - Système sur SSD 64 Go - /home sur HDD 500 Go.
Laptop: DELL Inspiron-15 3567 - Intel® Core™ i5-7200 CPU @ 2.50GHz × 4 - RAM 8 go - HDD 1 To - Ubuntu 20.10 avec /home séparé.
Mon site: Les contributions du bipède
Hors ligne
#5 Le 27/03/2008, à 17:25
- philou8237
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
ce que tu fais c'est du polling, cad. tu fais de l'écoute active en attente d'un évènement. Tu consommes donc tout ton quantum de temps à attendre, car bien sur read est bloquant pour ton processus si il n'est pas multithreadé.
si tu te bases sur l'usbhid, c que ton joystick ne possède pas de pilote linux. Ce que je te conseilles dans ce cas, c'est d'effectivement rédiger un pilote pour le joystick en utilisant l'API du noyau linux (cf. le livre d'o'reilly sur le developpement de pilote pour linux, ou sinon, je pense que sur la LKML tu trouvera des infos).
Le principe :
- ton joystick emets des données sur son port usb parce que... je sais pas ... tu l'a trituré.
- le controleur usb va ensuite emettre une requette au près du processeur
- le processeur va emettre une requette d'interruption, utilisant un tableau qui aura été préalablement créé par Linux. Il va donc arréter la tache en cours, et aller éxecuter le handler d'interruption du noyau linux.
- ce faisant, il va exécuter du code noyau, le temps de traiter l'interruption
- c'est là qu'intervient le pilote de périphérique. Il faut que le noyau aille exécuter la routine du pilote que tu auras rédigé, pour ça il faut l'informer que quand le joystick cause, il doit exécuter ta routine (cf. "write Linux driver" sur google ).
- Ensuite dans ta routine tu peux faire beaucoup de choses, dont ... écrire sur une socket par exemple, sur le port 1234 (non ça c'est déjà pris par giFT...) 1235 de ton interface lo.
- à coté, tu as un logiciel client, qui écoute cette interface avec un read non bloquant (man 2 read, c'est une option), et donc faire son traitement pépère, en gérant sa fenêtre en meme temps, un peu comme le font tous les clients ftp and co, sauf que là c'est une socket unix.
edit: plus simplement tu peux faire un read non bloquant. Par contre à toi de gérer le reste de la boucle qd le read n'a rien lu !
Je vais me rentrer, je serai de nouveau devant vers 18h15.
Dernière modification par philou8237 (Le 27/03/2008, à 17:26)
Hors ligne
#6 Le 27/03/2008, à 17:26
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
je raffrachi déjà mon interface comme ça
concernant le développement d'un pilote, c'était envisagé mais quand on a demandé la doc au constructeur il nous a envoyé sur un site qui ne contient une doc incomplète et pour un autre volant, je ne vois donc pas comment écrire un pilote.
PS : normalement le logiciel doit aller avec le logitech G25
J'ai survoler http://www.freesoftwaremagazine.com/art … page=0%2C0, si j'ai à peu prés compris, je code du C normal pour définir le driver, c'est ça, donc à la limite, je peux juste "renommer les fonction qui éxistent (open, close...) et modifier que le read ? Par contre concernant le read, je n'ai pas compris comment le rendre non bloquant, faut-il utiliser fcntl ?
Dernière modification par rniamo (Le 27/03/2008, à 17:40)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#7 Le 27/03/2008, à 18:30
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
phillou, tu pourrais développer ton edit stp, j'ai modifier le code comme suit :
if ((fd = open(f->peripherique, O_RDONLY | O_NONBLOCK)) < 0) /* */
{
perror("Erreur periph");
return;
}
....
do
{
lu=read(fd, &js, sizeof(struct js_event));
switch(lu)
{
case -1:
if ( errno == EAGAIN )
{
sleep(timeout);
continue;
}
break;
default:
break;
}
if ( lu!= sizeof(struct js_event) )
{
perror("\nErreur read() : ");
return;
}
...
}while();...
malheureusement j'ai mal géré le read "non bloquant" et je n'ai plus aucune réaction de mon joystick.
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#8 Le 27/03/2008, à 18:45
- philou8237
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
mmm... ça dépend ce que tu veux faire. Si tu veux effectivement coder un module du noyau, tu peux te baser sur ce tutoriel. Il te faudra cependant voir en profondeur pour que ton code soit appellé JUSTEMENT quand ton joystick cause.
Ce serait bien que tu rédiges un ptit driver, même si il ne "traite" pas le joystick mais ne fais que réagir quand il reçoit des données. ça pourra toujours servir à rédiger un driver complet plus tard.
Attention au fait qu'un certain nombre de fonctions de la libc sont remplacées par des fonctions du kernel (en fait, c pour que le kernel puisse démarrer avant de charger la libc.
par contre... pitié pas de gtk ni d'interaction directe avec l'utilisateur dans du code noyau ! tu casse le principe du shell intermédiaire, c tout vilain. Passe par l'intermédiaire d'une appli tierse qui dialogue avec le noyau, mais en étant en userland.
pour le read, un petit man 2 open te donnera une option, O_NONBLOCK, qui, lorsque c'est possible, rend les actions sur le fd découlant du open non bloquantes, dont le read.
Attention cependant, c'est plus dur de gérer les read, wait, etc... non bloquant, car justement il ne sont pas bloquant, et tu vas donc éxecuter le code qui suit à chaque tour de boucle.
edit: Hum... posts croisés... atta je lis
Dernière modification par philou8237 (Le 27/03/2008, à 18:46)
Hors ligne
#9 Le 27/03/2008, à 18:52
- philou8237
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
as tu bien vérifié que le open fonctionnait bien en non bloquant ? c'est très dépendant du type de fichier que tu ouvres. Genre en mettant un printf ds ton switch partie EAGAIN. Voir si il affiche régulièrement le contenu du printf, meme sans que tu touches le joystick.
essaies aussi de remplir ta partie default. Sinon comme ça ça me parait correct.
Hors ligne
#10 Le 27/03/2008, à 19:02
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
en sortie (des printf) j'obtient :
default
default
default
default
default
default
default
default
default
default
default
default
default
default
default
default
default
default
eagain
et je reste bloqué sur ce eagain.
NB : j'ai mis printf("eagain\n"); dans le case -1 et printf("default\n "); pour le default.
Concernant le programmation d'un driver, je n'ai pas le temps de me plonger dedans pour le moment (mais j'ai trouvé un tuto avec des led assez sympa) donc si l'option du read() pouvez suufir se serait bien.
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#11 Le 27/03/2008, à 19:12
- philou8237
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
mmmm c pas évident de savoir où est l'erreur. Il faudrait que tu fasses un coup de gdb, avec un break sur cette fonction, et que tu la fasse s'executer avec des steps, pour voir où précisément il s'arrête, en mettant un display js pour voir.
Utilise l'option -g3 pour avoir les symboles de débug.
Hors ligne
#12 Le 27/03/2008, à 21:46
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
j'ai pas d'erreur (malheureusement j'ai envie de dire), quand je dis je reste bloqué, c'est que je ne reçois plus de signaux .
le problème peut aussi venir du sleep (timeout=3 dans mon cas), pendant ce temps, pas d'interception de signaux...
je viens de voir un problème, un "return" un peu hatif...mais il doit y en avoir d'autre.
MEEEEERRRRRRRRCCCCCCCIIIIIIIIIIIIIIIIIIIIIIII . ça marche nikel . J'avais un petit problème de condition en plus.
Dernière modification par rniamo (Le 27/03/2008, à 21:58)
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#13 Le 28/03/2008, à 10:26
- Karl_le_rouge
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
On n'utilise pas sleep ni usleep, on lui préfére nanosleep qui d'après Posix n'utilise pas de signaux (et donc sans effets de bords).
Mieux vaut utiliser des appels bloquants sur des descripteurs de fichiers que de l'attente active, le kernel gèrera ça beaucoup mieux et de façon plus efficace que toi.
D'ailleurs, si c'est de l'usb, il est préférable d'utiliser libusb pour réaliser un pilote en espace utilisateur (et non pas un module noyau).
Hors ligne
#14 Le 28/03/2008, à 12:14
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
je n'ai pas le temps d'écrire un pilote mais je vais regarder nanosleep
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne
#15 Le 28/03/2008, à 18:54
- Link31
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
Il y a select() (combiné avec un read()) pour lire un descripteur de fichier de mode non-bloquant. Ça a l'air assez complexe à utiliser, mais ça semble aussi être la méthode la plus standard, étant donné le nombre d'occurrences de select() sur la souris dans le strace de n'importe quel programme graphique.
Dernière modification par Link31 (Le 28/03/2008, à 18:55)
Hors ligne
#16 Le 28/03/2008, à 21:21
- rniamo
Re : while(1), y a pas mieux ? [Si, y a mieux : Résolu]
oui c'est vrai, j'avais vu ce select...mais il est aussi vrai qu'il me semblait complexe hors le but du logiciel est minime, juste tester en visuel un joystick/volant.
< Quelques un des mes programmes | Cuisine Facile (pour les gourmands) | Fast MVC for PHP >
\ ^__^
\ (o o)\_______
(___)\ )\
Hors ligne