Los resultados de printf() y system() están en el orden incorrecto cuando la salida se redirige a un archivo
linux child-process (3)
De forma predeterminada, la salida a la salida estándar está en búfer de línea cuando se conecta a un terminal. Es decir, el búfer se vacía cuando está lleno o cuando agrega una nueva línea.
Sin embargo
, si
stdout
no está conectado a un terminal, como lo que sucede cuando redirige la salida de su programa a un archivo, entonces
stdout
convierte en
un búfer completo
.
Eso significa que el búfer se vaciará y en realidad se escribirá cuando esté lleno o cuando se vacíe explícitamente (lo que sucede cuando el programa sale).
Esto significa que la salida de un proceso separado iniciado desde su código (como lo que sucede cuando llama al
system
) probablemente se escribirá primero, ya que el búfer de ese proceso se vaciará cuando finalice ese proceso, que es antes de su propio proceso.
¿Qué sucede cuando se usa la redirección (o las tuberías)?
-
Su llamada a
printf
escribe en el búferstdout
. -
La función del
system
inicia un nuevo proceso, que escribe en su propio búfer. -
Cuando el proceso externo (iniciado por su llamada al
system
) sale, su búfer se vacía y se escribe. Tu propio búfer en tu propio proceso, no se toca. -
Su propio proceso termina, y su búfer de
stdout
se vacía y se escribe.
Para obtener la salida en el orden "correcto" (o al menos esperado), llame a
fflush
antes de llamar al
system
, para eliminar explícitamente la salida
setbuf
, o llame a
setbuf
antes de cualquier salida para deshabilitar el almacenamiento en búfer por completo.
Esta pregunta ya tiene una respuesta aquí:
Tengo un programa en C que se compila en un ejecutable llamado myprogram. Esta es su función principal:
int main(int argc, char ** argv) {
printf("this is a test message./n");
system("ls");
return 0;
}
Cuando ejecuto
myprogram > output.txt
en un shell de Linux y luego examino output.txt, veo el resultado de
ls
arriba "este es un mensaje de prueba".
Siento que debería ser al revés. ¿Por qué sucede esto y qué puedo hacer para que aparezca "este es un mensaje de prueba" en la parte superior de output.txt?
Si importa, soy nuevo en C y trabajo en una línea de comandos.
Está relacionado con el búfer de salida. Logré reproducir el mismo comportamiento. Forzando el color lo hizo por mí.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv) {
printf("this is a test message./n");
fflush(stdout);
system("ls");
return 0;
}
Antes de añadir el fflush:
$ ./main > foo
$ cat foo
main
main.c
this is a test message.
y después:
$ ./main > foo
$ cat foo
this is a test message.
foo
main
main.c
Sospecho que es por el orden en el que se descarga el búfer de la salida estándar, lo que no es necesariamente determinista.
Es posible que el padre genere el proceso
ls
y no elimine su propia salida estándar hasta que vuelva.
Es posible que no descargue la salida estándar hasta que finalice el proceso.
Intente agregar
fflush (stdout)
después de la declaración printf y vea si eso fuerza a que la salida aparezca primero.