question de base sur l'informatique

La question :

Bonjour,

il me semble que cette question a sa place sur fr.comp.developpement,
mais je n'en suis pas sûr, alors je double sur fr.comp.divers et vous
demande de me rediriger au bon endroit

Je m'interroge sur un fonctionnement de base de l'informatique.

Quand un logiciel attend une action : un clic de souris, une frappe au
clavier ou tout autre chose, comment fait-il pour distinguer l'action
de l'inaction ?

Mon hypothèse est qu'il y a un truc qui tourne sans arrêt pour aller
vérifier l'état des... heu... "interupteurs", mais on me dit que c'est
pas ça (sans me dire ce que c'est)

Vous savez ?

--
siger

Poser votre question sur le forum Programmation

Les 4 réponses :

In fr.comp.developpement siger <s@s.invalid> a écrit :


Quand un logiciel attend une action : un clic de souris, une frappe au
clavier ou tout autre chose, comment fait-il pour distinguer l'action
de l'inaction ?


En fait, la plupart des logiciels manipulant des interfaces graphiques
utilisent un modèle de programmation appelé `événementiel'.

Dans son implémentation la plus simple, on peut imaginer que les
actions attendues (les événements) sont simplement liés à des
fonctions de votre logiciel. Lorsque l'événement X survient, la
fonction traiter_X() est appelée. On appelait cela il y a longtemps
des `callbacks'. Ces callbacks doivent être associés aux événements
en appelant une fonction de l'OS ou du GUI correspondant.

L'inaction est donc quand après un certain délai (un délai est
aussi un événement dans ce modèle, c'est plus simple), rien ne s'est passé.

En supposant un système géré de manière séquentielle(*), le pseudo-code
ressemblerait(**) à:

int il_a_clique = 0;

associer(UN_CLICK, &traiter_CLIC);
associer(UN_DELAI_DE_5_SECONDES, &traiter_DELAI);

void traiter_CLIC() {
il_a_clique = 1;

// alternative: annuler le délai et directement appeler traiter_DELAI()
}

void traiter_DELAI() {
if (il_a_clique) {
puts("click reçu");
}
else {
puts("t'as pas clique");
}
}

Une autre technique est de transformer ces appels directs de
fonctions par des messages (des octets dans un pipeline, dans un
socket, dans une connexion TCP, etc). L'avantage de cette sérialisation
est la possibilité de prioriser les événements à la réception, la
détection du non traitement des événements après un timeout ("l'application
X ne répond pas"), et la possibilité de faire des interfaces graphiques
déportées (cf ssh -X) de manière triviale ou presque.

Dans ce cas, le logiciel est conçu comme un gros:

while (1) {
m = lire_message();
traiter_message(m);
}

La fonction lire_message() est bloquante (le processus est endormi
par l'OS). Ca peut d'ailleurs même marcher avec des OS non réellement
multitâches: on autorise l'OS à changer de tâche alors uniquement au
sein de lire_message() par un `yield()' manuel, p.ex. Ca a dû être ainsi
que le multitâche dit `coopératif' de certains vieux OS fonctionnait.
En conséquence, si traiter_message() prend trop de temps, sur ces
vieux OS, l'expérience utilisateur sera très saccadée. Je crois savoir
que Javascript dans un navigateur Web est en fait un langage de ce type,
les experts commenteront.

(*) si au contraire, les événements peuvent être traités en parallèle,
le code ci-dessous n'est pas bon car il ne gère pas la concurrence
(suivant sa complexité, il faudrait ajouter des verrous, etc)

(**) après avoir écrit cet exemple en C, dû à mon passé de développeur
embarqué, je me suis dit: tiens, j'aurais dû faire un exemple en
Javascript (association d'événement "click" à un élément HTML,
puis un window.setTimeout()), je laisse ça en devoir :->


Mon hypothèse est qu'il y a un truc qui tourne sans arrêt pour aller
vérifier l'état des... heu... "interupteurs", mais on me dit que c'est
pas ça (sans me dire ce que c'est)


C'est possible aussi, mais c'est pas efficace du tout. L'OS entier *peut*
être finalement conçu pour générer les appels de fonctions (un peu
moche directement depuis une interruption bas niveau) ou les
événements ci-dessus: il suffit de générer un événement lorsqu'une
interruption matérielle (clavier, souris, etc) est générée.

La plupart des OS modernes ne fonctionnent pas avec du `polling' comme
tu décris mais des interruptions et des files de messages.

Le seul cas récent où j'ai vu du polling pour des événements (à part
des optimisations de lecture de nombreux capteurs, mais c'est hors
sujet) c'est avec le logiciel de "Media center" XBMC (aka Kodi),
c'est d'ailleurs effrayant de voir le CPU qui chauffe

Marc SCHAEFER a écrit :


In fr.comp.developpement siger <s@s.invalid> a écrit :


Quand un logiciel attend une action : un clic de souris, une
frappe au clavier ou tout autre chose, comment fait-il pour
distinguer l'action de l'inaction ?


En fait, la plupart des logiciels manipulant des interfaces
graphiques utilisent un modèle de programmation appelé
`événementiel'.


Je ne pensais pas forcément à une interface graphique, ça peut être
l'état d'un interrupteur connecté à une carte PCI ou en USB pour une
action quelconque



(...)



Mon hypothèse est qu'il y a un truc qui tourne sans arrêt pour
aller vérifier l'état des... heu... "interupteurs", mais on me
dit que c'est pas ça (sans me dire ce que c'est)



C'est possible aussi, mais c'est pas efficace du tout. L'OS entier
*peut* être finalement conçu pour générer les appels de fonctions
(un peu moche directement depuis une interruption bas niveau) ou
les événements ci-dessus: il suffit de générer un événement
lorsqu'une interruption matérielle (clavier, souris, etc) est
générée.

La plupart des OS modernes ne fonctionnent pas avec du `polling'
comme tu décris mais des interruptions et des files de messages.


OK, merci.

Je n'ai pas compris ton explication, sans doute parce que ce sont des
choses que je ne connais pas, mais je note que le "polling" a existé et
ne se fait plus ou presque



--
siger

siger <s@s.invalid> a écrit :


Je n'ai pas compris ton explication, sans doute parce que ce sont des


C'est dommage: je clarifie volontiers ce qui manque.

Un concept qui te manque peut-être est la notion d'interruption de processeur.

Lorsqu'un événement d'un périphérique au CPU survient, le périphérique
lève une interruption (un bit dans un registre) qui provoque assez vite
la suspension de ce qu'est entrain de faire le processeur et l'appel
d'une fonction d'interruption qui va déterminer ce qui s'est passé,
interroger le périphérique, etc puis générer des messages à l'intention
de l'OS puis des applications (p.ex: je viens de lire un octet d'un
port série, le bloc I/O demandé du périphérique SATA 3 est là, etc).

A partir de là, toute une chaîne de traitement est lancée à plusieurs
niveaux (bas niveau: interruption; niveau intermédiaire: pilote de
périphérique / interruptions `soft', timers et tâches kernel; haut niveau:
application en user-space), basé soit sur des messages (stockés dans des
queues de message en mémoire), soit sur des appels direct de code
(callbacks), soit un mélange des deux.

Finalement, en bout de ligne, c'est l'application qui se voit réveillée
et traite un message de plus (cf la boucle en pseudo-code).


choses que je ne connais pas, mais je note que le "polling" a existé et
ne se fait plus ou presque


Il reste des raisons de faire du polling, p.ex. lorsqu'il y a tellement
d'événements à traiter que le traiter en mode interruption signifierait
passer son temps dans la gestion des interruptions.

Ou pour des circuits simples où un mode interruption serait trop compliqué.

Ou dans des cas où l'overhead (le coût) du traitement des interruptions
est prohibitif.

Concrètement, quand je faisais des contrôleurs RAID, je travaillais en
hybride:

- la toute première requête je la recevais en polling, pour gaspiller
le moins de microsecondes possible (interruption == sauver le contexte
actuel, sauter à une routine, restaurer le contexte)

- toutes les requêtes reçues et envoyées pendant le traitement de cette
première requête étaient traitées en mode interruption, en parallèle, avec
un avantage de pipelining (genre: pendant qu'on attend la réponse
d'un des N disques-dur RAID, on peut décoder des commandes qui viennent
du host en parallèle)

- dès que le système revenait en mode `idle' (fin du traitement de toutes
les requêtes), la requête suivante était traitée en mode polling.

Avec ça, je gagnais pas mal de temps de traitement (~20 microsecondes
de mémoire) sur la 1ère requête en mode idle. Et dès que le système
passait en mode parallèle, de toute façon la latence du traitement
des interruptions était compensée par le bénéfice du traitement parallèle.

Marc SCHAEFER a écrit :


siger <s@s.invalid> a écrit :


Je n'ai pas compris ton explication, sans doute parce que ce sont
des


C'est dommage: je clarifie volontiers ce qui manque.

Un concept qui te manque peut-être est la notion d'interruption de
processeur.

Lorsqu'un événement d'un périphérique au CPU survient, le
périphérique lève une interruption (un bit dans un registre) qui
provoque assez vite la suspension de ce qu'est entrain de faire le
processeur et l'appel d'une fonction d'interruption qui va
déterminer ce qui s'est passé, interroger le périphérique, etc
puis générer des messages à l'intention de l'OS puis des
applications (p.ex: je viens de lire un octet d'un port série, le
bloc I/O demandé du périphérique SATA 3 est là, etc).

A partir de là, toute une chaîne de traitement est lancée à
plusieurs niveaux (bas niveau: interruption; niveau intermédiaire:
pilote de périphérique / interruptions `soft', timers et tâches
kernel; haut niveau: application en user-space), basé soit sur des
messages (stockés dans des queues de message en mémoire), soit sur
des appels direct de code (callbacks), soit un mélange des deux.

Finalement, en bout de ligne, c'est l'application qui se voit
réveillée et traite un message de plus (cf la boucle en
pseudo-code).


choses que je ne connais pas, mais je note que le "polling" a
existé et ne se fait plus ou presque


Il reste des raisons de faire du polling, p.ex. lorsqu'il y a
tellement d'événements à traiter que le traiter en mode
interruption signifierait passer son temps dans la gestion des
interruptions.

Ou pour des circuits simples où un mode interruption serait trop
compliqué.

Ou dans des cas où l'overhead (le coût) du traitement des
interruptions est prohibitif.



Merci pour ces explications

--
siger

Poser votre question sur le forum Programmation

Questions similaires :

question de licence: GNU GPL et communication via des fichiers

Bonjour, J'ai encore une question de licence. Peut-on envisager un programme propriétaire (code source non fourni) qui utilise des outils GPL, mais uniquement en communiquant par des fichiers (pas de code GPL dans le code source du programme propriétaire, pas de link dynamique non plus)....

Visual C++ (petite question)

Bonjour, Je développe un jeu de plateau avec VC++ 6.0 de Microsoft. J'ai créé un plateau de jeu avec 64 cases qui sont autant de boutons (classe CButton des MFC). Le problème, c'est que pour gérer le clic sur chacun des boutons, je risque de me retrouver avec 64 fonctions OnClick()...

offre de stage informatique

La société PERVAYA, éditeur de logiciel informatique en plein développement, est à la recherche de deux stagiaires informatiques Bac+3 à Bac+4/5. Durée : 5 à 6 mois, début janvier/février 2006. Tâches Ce stage pourra déboucher à un poste d'Ingénieur Informatique au sein de notre...

QUESTION SUR FREE.FR ET PHP

Je suis développeur et je dois créer un site web pour un client. Il compte placer son site php sur Free.fr. Ma question est de savoir si le XML est accepté sur ce serveur et si oui, quelle est la librairie activée ? Merci de me répondre, Roland

logiciel pour création d'une base de données

Bonjour, Auriez-vous un logiciel à me conseiller pour faire la conception d'une base de données, création des tables, des liens etc ... ? avec génération des scripts qui conviendrait à une base MySql ? C'est pour un developpement perso. Quelque chose de gratuit, graphique et intuitif serait le...