De la lectura de las páginas del manual sobre el read()
y write()
llamadas parece que estas llamadas quedan interrumpidos por las señales independientemente de si tienen o no bloquear.
En particular, asuma
- Un proceso establece un controlador para alguna señal.
- se abre un dispositivo (por ejemplo, un terminal) con el
O_NONBLOCK
no configurado (es decir, opera en modo de bloqueo) - el proceso realiza una
read()
llamada al sistema para leer desde el dispositivo y, como resultado, ejecuta una ruta de control de kernel en kernel-space. - mientras el preceso está ejecutando su
read()
espacio en el núcleo, la señal para la que se instaló el controlador anteriormente se entrega a ese proceso y se invoca su controlador de señal.
Al leer las páginas de manual y las secciones correspondientes en SUSv3 'Volumen de interfaces del sistema (XSH)' , se encuentra que:
yo. Si a read()
es interrumpido por una señal antes de leer cualquier dato (es decir, tuvo que bloquear porque no había datos disponibles), devuelve -1 con errno
set en [EINTR].
ii) Si a read()
es interrumpido por una señal después de haber leído con éxito algunos datos (es decir, fue posible comenzar a atender la solicitud de inmediato), devuelve el número de bytes leídos.
Pregunta A):
¿Estoy en lo cierto al suponer que en cualquier caso (bloqueo / no bloqueo) la entrega y el manejo de la señal no es completamente transparente para el read()
?
Caso i. parece comprensible ya que el bloqueo read()
normalmente colocaría el proceso en el TASK_INTERRUPTIBLE
estado de modo que cuando se entrega una señal, el núcleo coloca el proceso en TASK_RUNNING
estado.
Sin embargo, cuando read()
no es necesario bloquear (caso ii.) Y está procesando la solicitud en kernel-space, habría pensado que la llegada de una señal y su manejo serían transparentes, como la llegada y el manejo adecuado de un HW la interrupción sería En particular, habría asumido que al entregar la señal, el proceso se colocaría temporalmente en modo de usuario para ejecutar su controlador de señal desde el cual volvería finalmente para terminar de procesar el interrumpido read()
(en el espacio del kernel) para que se read()
ejecute su curso hasta su finalización después de lo cual el proceso vuelve al punto justo después de la llamada a read()
(en el espacio de usuario), con todos los bytes disponibles leídos como resultado.
Pero ii. parece implicar que read()
se interrumpe, ya que los datos están disponibles de inmediato, pero devuelve solo algunos de los datos (en lugar de todos).
Esto me lleva a mi segunda (y última) pregunta:
Pregunta B):
Si mi suposición bajo A) es correcta, ¿por qué read()
se interrumpe, a pesar de que no necesita bloquearse porque hay datos disponibles para satisfacer la solicitud de inmediato? En otras palabras, ¿por qué read()
no se reanuda después de ejecutar el controlador de señal, y finalmente se devuelven todos los datos disponibles (que estaban disponibles después de todo)?