2012-01-23 24 views
14

Considere la siguiente línea de código:lectura() desde la entrada estándar

while((n = read(STDIN_FILENO, buff, BUFSIZ)) > 0) 

Según mi entendimiento read/write funciones son una parte de E/S sin almacenamiento intermedio. Entonces, ¿eso significa que la función read() leerá solo un carácter por llamada de stdio? O en otras palabras, el valor de n será

-1 in case of error 
n = 0 in case of EOF 
    1 otherwise 

Si no es el caso, ¿cuándo la función anterior devolverá read() y por qué?

Nota: También estaba pensando que read() esperará hasta que lea con éxito BUFSIZ número de caracteres de stdin. Pero lo que sucede en un número de casos de caracteres disponibles para leer es menor que BUFSIZ? Se leerá esperar por siempre o hasta que llegue EOF (Ctrl + D en Unix o Ctrl + Z en Windows)?

Además, digamos BUFSIZ = 100 y stdin = ACtrl+D (es decir, EOF inmediatamente después de un solo carácter). Ahora, ¿cuántas veces se iterará el while loop?

+2

Como un FYI, creo que puede 'leer' de' 0', que es una entrada estándar, pero solo puede usar 'stdin' con' fread() '. –

+0

sí, tienes razón ... ¡zas! Como stdin es del tipo 'FILE *' no se puede usar con 'read' –

+3

o' STDIN_FILENO' si está de humor para etiquetar. – Dave

Respuesta

2

Como los read() estados página de manual:

Valor de retorno

En caso de éxito, se devuelve el número de bytes leídos (cero indica el final del fichero), y la posición del fichero es avanzado por este número. No es un error si este número es menor que el número de bytes solicitados; esto puede suceder, por ejemplo, porque actualmente hay menos bytes disponibles (tal vez porque estábamos cerca del final del archivo, o porque estamos leyendo desde un conducto, o desde un terminal), o porque read() fue interrumpido por una señal. En caso de error, se devuelve -1, y errno se establece de forma adecuada. En este caso, no se especifica si la posición del archivo (si hay alguna) cambia.

Así, cada read() leerán hasta el número de bytes especificados; pero puede leer menos. "Sin búfer" significa que si especifica read(fd, bar, 1), leer solo leerá un byte. Buffer IO intenta leer en cuantos de BUFSIZ, incluso si solo quiere un carácter. Esto puede parecer un desperdicio, pero evita la sobrecarga de hacer llamadas al sistema, lo que lo hace más rápido.

+0

tu respuesta es demasiado genérica ... amablemente, sé más específico con el problema –

0
  1. read intenta obtener todos los caracteres solicitados.
  2. si ocurre EOF antes de que se puedan devolver todos los caracteres solicitados, devuelve lo que obtuvo después de esto, la siguiente lectura devuelve -1, para hacerle saber el final del archivo.

Lo que sucede cuando trata de leer y no hay nada implica algo llamado bloqueo. Puede llamar a abrir para leer un archivo que bloquea o no bloquea. "bloqueo" significa esperar hasta que haya algo que devolver.

Esto es lo que se ve en un intérprete de comandos esperando la entrada. Se sienta allí. Hasta que toques el retorno.

No-bloqueo significa que read no devolverá bytes de datos si no los hay.Dependiendo de muchos otros factores que harían inutilizable una respuesta completamente correcta, leer configurará errno en algo como EWOULDBLOCK, que le permite saber por qué su lectura arrojó cero bytes. No es necesariamente un error fatal.

Su código podría probar un signo menos para encontrar errores o EOF

17

La manera de leer() se comporta depende de lo que se lee. Para archivos regulares, si solicita N caracteres, obtendrá N caracteres si están disponibles, menos de N si interviene el final del archivo.

Si read() está leyendo desde un terminal en modo canónico/cocido, el controlador tty proporciona datos una línea a la vez. Entonces, si le dice a read() que obtenga 3 caracteres o 300, la lectura se bloqueará hasta que el controlador tty haya visto una nueva línea o la tecla EOF definida del terminal, y luego read() regresará con el número de caracteres en la línea o el número de caracteres que solicitó, el que sea menor.

Si read() lee desde un terminal en modo no canónico/raw, read tendrá acceso a las pulsaciones de tecla inmediatamente. Si le pide a read() que obtenga 3 caracteres, puede regresar con 0 a 3 caracteres, dependiendo del tiempo de entrada y cómo se configuró la terminal.

read() se comportará de manera diferente ante las señales, regresando con un número de caracteres menor que el solicitado, o -1 con errno configurado en EINTR si una señal interrumpió la lectura antes de que llegaran los caracteres.

read() se comportará de manera diferente si el descriptor se ha configurado para E/S sin bloqueo. read() devolverá -1 con errno establecido en EAGAIN o EWOULDBLOCK si no hay entradas disponibles de inmediato. Esto aplica a los enchufes.

Como puede ver, debe estar listo para las sorpresas cuando llame a read(). No siempre obtendrás la cantidad de caracteres que solicitaste, y es posible que obtengas errores no fatales como EINTR, lo que significa que debes volver a intentar leer().

+0

ohh ... en realidad extraño escribir el paréntesis ... ¡¡¡tx !! –

+0

ahora vuelve al problema real. –

3

Su código lee:

while((n = read(0, buff, BUFSIZ) != 0)) 

Esta es defectuoso - los paréntesis significan que se interpreta como:

while ((n = (read(0, buff, BUFSIZ) != 0)) != 0) 

donde se evalúa la condición booleana antes de la asignación, por lo n será solamente obtener el valores 0 (la condición no es verdadera) y 1 (la condición es verdadera).

Usted debe escribir:

while ((n = read(0, buff, BUFSIZ)) > 0) 

Esto se detiene en EOF o un error de lectura, y n le permite saber qué condición que encontró.


Aparentemente, el código anterior era un error tipográfico en la pregunta.

E/S sin búfer leerá hasta la cantidad de caracteres que lea (pero no más). Puede leer menos a causa de EOF o un error. También puede leer menos porque hay menos disponible en el momento de la llamada. Considera una terminal; típicamente, eso solo se leerá hasta el final de la línea porque no hay más disponible que eso. Considera una pipa; si el proceso de alimentación ha generado 128 bytes no leídos, entonces si BUFSIZ es 4096, solo obtendrá 128 bytes de la lectura.Un descriptor de archivo no bloqueante puede regresar porque no hay nada disponible; un socket puede devolver menos bytes porque aún no hay más información disponible; una lectura de disco puede devolver menos bytes porque hay menos cantidad de bytes solicitados en el archivo cuando se realiza la lectura.

En general, sin embargo, read() no devolverá solo un byte si solicita muchos bytes.

+0

que era un error tipográfico ... lo he solucionado ... ahora vuelvo al problema real. –

0

Cuando decimos que read está sin búfer, significa que no hay almacenamiento en búfer en el nivel de su proceso después de que los datos se extrajeron de la descripción del archivo abierto subyacente, que es un recurso potencialmente compartido. Si stdin es un terminal, es probable al menos 2 tampones adicionales en juego, sin embargo:

  1. El tampón de terminal, lo que probablemente puede contener 1-4k de datos fuera de la línea hasta.
  2. El buffer del modo cocido/canónico del kernel para entrada/edición de línea en un terminal, que permite al usuario realizar la edición primitiva (retroceso, backword, línea de borrado, etc.) en la línea hasta que se envía (al búfer descrito anteriormente) presionando enter.

read extraerá lo que ya se haya enviado, hasta la longitud máxima de lectura que le haya pasado, pero no puede extraer nada del buffer de edición de línea. Si desea deshabilitar esta capa adicional de almacenamiento en búfer, debe buscar cómo desactivar el modo cocido/canónico para un terminal usando tcsetattr, etc.

Cuestiones relacionadas