En lisant les pages de manuel sur les appels read()
et, write()
il apparaît que ces appels sont interrompus par des signaux, qu'ils soient bloqués ou non.
En particulier, supposons
- un processus établit un gestionnaire pour un certain signal.
- un appareil est ouvert (disons un terminal) avec le
O_NONBLOCK
non réglé (c'est-à-dire fonctionnant en mode blocage) - le processus effectue ensuite un
read()
appel système pour lire à partir du périphérique et, par conséquent, exécute un chemin de contrôle du noyau dans l'espace noyau. - tandis que le prédécesseur exécute son
read()
dans l'espace noyau, le signal pour lequel le gestionnaire a été installé précédemment est envoyé à ce processus et son gestionnaire de signal est appelé.
En lisant les pages de manuel et les sections appropriées dans SUSv3 'System Interfaces volume (XSH)' , on constate que:
je. Si a read()
est interrompu par un signal avant de lire des données (c'est-à-dire qu'il a dû bloquer car aucune donnée n'était disponible), il renvoie -1 avec errno
la valeur [EINTR].
ii. Si a read()
est interrompu par un signal après avoir lu avec succès certaines données (c'est-à-dire qu'il était possible de commencer à traiter la demande immédiatement), il renvoie le nombre d'octets lus.
Question A):
Ai-je raison de supposer que dans les deux cas (bloc / pas de bloc) la livraison et la gestion du signal ne sont pas entièrement transparentes pour le read()
?
Cas i. semble compréhensible car le blocage read()
placerait normalement le processus dans l' TASK_INTERRUPTIBLE
état de sorte que lorsqu'un signal est délivré, le noyau place le processus dans l' TASK_RUNNING
état.
Cependant, lorsque le read()
n'a pas besoin de bloquer (cas ii.) Et traite la demande dans l'espace noyau, j'aurais pensé que l'arrivée d'un signal et sa gestion seraient transparentes, tout comme l'arrivée et la gestion appropriée d'un HW l'interruption serait. En particulier , j'ai supposé que lors de la livraison du signal, le processus serait placé temporairement en mode utilisateur pour exécuter son gestionnaire de signal à partir duquel il reviendrait finalement pour finir le traitement de l'interruption read()
(dans l'espace du noyau) de sorte que le read()
court son cours jusqu'à la fin, après quoi le processus revient au point juste après l'appel à read()
(dans l'espace utilisateur), avec tous les octets disponibles lus en conséquence.
Mais ii. semble impliquer que le read()
est interrompu, car les données sont disponibles immédiatement, mais il retourne ne renvoie que certaines des données (au lieu de toutes).
Cela m'amène à ma deuxième (et dernière) question:
Question B):
Si mon hypothèse sous A) est correcte, pourquoi l' read()
interruption est-elle interrompue, même si elle n'a pas besoin d'être bloquée car des données sont disponibles pour satisfaire immédiatement la demande? En d'autres termes, pourquoi le n'est-il read()
pas repris après l'exécution du gestionnaire de signal, ce qui a finalement pour résultat de renvoyer toutes les données disponibles (qui étaient disponibles après tout)?