Como se describe en SUSv4 o POSIX.1-2008
http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html#tag_16_685_08
La llamada write() puede devolver un valor menor que nbytes si escribe () en una tubería NONBLOCK/FIFO . Por lo tanto, es necesario verificar el valor devuelto y escribir () el resto del búfer en un ciclo que se muestra a continuación:
while (bytes_to_write > 0) { select(...); // Or poll() retv = write(...); if (retv < 0) ... // Error bytes_to_write -= retv; }El estándar no dice nada sobre archivos regulares, archivos especiales (también conocidos como dispositivos) y sockets , especialmente sockets basados en flujo (sockets TCP y dominios UNIX, por ejemplo).
Entonces, tengo las siguientes dos preguntas:
Perdón por el inglés roto.
Está bien. Dado que el estándar no proporciona ninguna garantía, no podemos asumir write() .
Busqué en Google escritura parcial v y obtuve una respuesta:
http://developerweb.net/viewtopic.php?id=4154
Sí, también he visto ese comportamiento antes (aunque con sendmsg() y sus iovecs)... Y, en realidad, NO es un comportamiento incorrecto/inesperado... Tanto read()/recv() como write( )/send() (y todas las permutaciones de las funciones de E/S) pueden devolver lecturas/escrituras cortas, y todo el código de los sockets debe estar preparado para lidiar con eso... No importa si están bloqueando o no. -bloqueo de sockets en modo, ya sea... Todo lo que controla es lo que sucede cuando el búfer está totalmente vacío (en el caso de la entrada) o totalmente lleno (en el caso de la salida)... Pero, cuando el búfer de envío no lo está bastante lleno, cualquier escritura en él (a través de un socket de bloqueo o no bloqueo) de más de la cantidad de espacio libre restante escribirá tanto como pueda, y luego devolverá el recuento de escritura corto ... Y, se espera que maneje llamarlo nuevamente, para enviar la cantidad restante ... Con write()/send() normal, es fácil de hacer, pero con writev()/sendmsg() iovecs, se vuelve complicado de manejar y un verdadero dolor ... Pero, todavía DEBES hacerlo
writev_all() no se puede evitar.
Gracias.
¿Se producirá una escritura parcial () (o envío parcial ()) en archivos normales?
Sí.
(o enchufes con O_NONBLOCK desarmado) ?
Sí.
¿Qué tal writev() y sendmsg() en sockets NONBLOCK?
Sí.
Esto es muy importante, ya que tratar con un vector parcialmente escrito (struct iovec []) es un poco problemático.
Realmente no. Usted sabe cuántos bytes se escribieron, solo tiene que avanzar los punteros y disminuir los tamaños en consecuencia. Si es demasiado problema para usted, use el modo de bloqueo.
¿Se producirá una
write()(osend()) en archivos normales (o sockets conO_NONBLOCKsin establecer)?
Posiblemente. Las señales pueden interrumpir cualquier operación de E/S, pero la biblioteca se reiniciará automáticamente según el indicador SA_RESTART :
Esta bandera afecta el comportamiento de las funciones interrumpibles; es decir, aquellos especificados para fallar con
errnoestablecido en [EINTR]. Si se establece, y esta señal interrumpe una función especificada como interrumpible, la función se reiniciará y no fallará con [EINTR] a menos que se especifique lo contrario. Si se reinicia una función interrumpible que utiliza un tiempo de espera, la duración del tiempo de espera que sigue al reinicio se establece en un valor no especificado que no supera el valor de tiempo de espera original. Si la bandera no está configurada, las funciones interrumpibles interrumpidas por esta señal fallarán conerrnoconfigurado en [EINTR].
Este indicador está configurado de forma predeterminada en Linux, por lo que no debe preocuparse a menos que esté en vigor el manejo personalizado de señales.
¿Qué
writev()ysendmsg()en socketsNONBLOCK? Esto es muy importante, ya que tratar con un vector parcialmente escrito (struct iovec []) es un poco problemático.
Las llamadas al sistema más complejas se manejan de la misma manera. El código de la biblioteca del espacio de usuario hace el trabajo pesado de reiniciar la llamada interrumpida, después de que el controlador de señal (si lo hay) haya regresado.