2012-02-17 20 views
7

La función writev toma una matriz de estructura iovec como argumento de entrada¿Cómo funciona la lista de escritura de E/S internamente?

writev(int fd, const struct iovec *iov, int iovcnt);

La entrada es una lista de los buffers de memoria que necesitan ser escritos en un archivo (por ejemplo). Lo que yo quiero saber es:

¿Se writev internamente hacer esto:

for (each element in iov) write(element)

de tal manera que cada elemento de iov está escrito a presentar en un separo de E/S llaman? O ¿writev escribe todo en el archivo en una llamada de E/S sola?

Respuesta

6

acuerdo a las normas, el bucle for que usted ha mencionado no es una aplicación válida de writev, por varias razones:

  1. El bucle podría dejar de terminar de escribir una iov antes de proceder a la siguiente, en el caso de una breve redacción, pero podría solucionarse haciendo que el ciclo sea más elaborado.
  2. El bucle podría tener un comportamiento incorrecto con respecto a la atomicidad de las tuberías: si la longitud total de escritura es menor que PIPE_BUF, la escritura de la tubería debe ser atómica, pero el bucle rompería el requisito de atomicidad. Este problema no se puede solucionar, excepto al mover todas las entradas de iov a un único búfer antes de escribir cuando la longitud total es a lo sumo PIPE_BUF.
  3. El bucle puede tener casos en los que podría resultar en bloqueo, donde la llamada única writev sería necesaria para realizar una escritura parcial sin bloqueo. Hasta donde yo sé, este problema sería imposible de solucionar en el caso general.
  4. Posiblemente otras razones que no he pensado.

No estoy seguro acerca del punto n. ° 3, pero definitivamente existe en la dirección opuesta, al leer. Llamar al read en un bucle podría bloquear si un terminal tiene algunos datos (más cortos que la longitud total de yodo) disponibles seguidos de un indicador EOF; llamando al readvdebe devolver inmediatamente con una lectura parcial en este caso. Sin embargo, debido a un error en Linux, readv en terminales se implementa realmente como un bucle read en el kernel, y muestra este error de bloqueo. Tenía que evitar este error en la aplicación de stdio de MUSL:

http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=commit;h=2cff36a84f268c09f4c9dc5a1340652c8e298dc0

Para responder a la última parte de su pregunta:

¿O writev escribir todo para presentar en una sola llamada de E/S ?

En todos los casos, una implementación conforme a writev será una syscall única. Abajo cómo se implementa en Linux: para archivos comunes y para la mayoría de los dispositivos, el controlador de archivos subyacente tiene métodos que implementan iov-style io directamente, sin ningún tipo de bucle interno.Pero el controlador del terminal en Linux está muy desactualizado y carece de los métodos io modernos, haciendo que el kernel retroceda a un ciclo de escritura/lectura para writev/readv cuando se opera en un terminal.

+0

No entiendo la última línea "cuando se opera en una terminal". Además, ¿dónde exactamente en el src de Linux compruebas la implementación de writev? – jitihsk

+0

"Cuando se opera en un terminal" significa cuando el descriptor de archivo se refiere a un dispositivo terminal. En cuanto a dónde en la fuente, http://lxr.linux.no/#linux+v3.2.6/fs/read_write.c#L809 –

3
Or does writev write everything to file in a single I/O call? 

No soy todo, aunque sys_writev intenta escribir todo en una sola llamada. depende del implemento de vfs, si el vfs no da un implemento de writev, entonces kenerl llamará a vfs 'write() en un bucle. es mejor verificar el valor de retorno de writev/readv para ver cuántos bytes se escriben como lo hace en write().

puede encontrar el código de writev en kernel, fs/read_write.c: do_readv_writev.

5

La forma directa de saber cómo funciona el código es leer el código fuente.

ver http://www.oschina.net/code/explore/glibc-2.9/sysdeps/posix/writev.c

Se alloca simplely() o malloc() un tampón, copie todos los vectores en ella, y la llamada de escritura() una vez.

Eso cómo funciona. Nada misterioso.

+0

Eso es glibc writev, no linux kernel writev. – Eloff

+0

Solo aprender sobre mempcpy desde ese enlace es una victoria épica. – RishiD

Cuestiones relacionadas