Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

152
Vistas
La salida del programa cambia cuando se canaliza

Tengo un programa C simple para iniciar el proceso de tiempo (preferiría no publicar el código completo ya que es una tarea escolar activa). Mi función principal se ve así:

 int main(void) { int i; for (i = 0; i < 5; i++) { printf("%lf\n", sample_time()); } exit(0); }

sample_time() es una función que mide el tiempo que se tarda en bifurcar un nuevo proceso y devuelve el resultado en segundos como un double . La parte de sample_time() que se bifurca:

 double sample_time() { // timing stuff if (!fork()) exit(0); // immediately close new process // timing stuff return a_sample_time; }

Como era de esperar, ejecutar el programa, times , en la terminal genera 5 números así:

 $ ./times 0.000085 0.000075 0.000079 0.000071 0.000078

Sin embargo, intentar redirigir esto a un archivo (oa cualquier otro lugar) en una terminal Unix produce resultados inesperados.

Por ejemplo, ./times > times.out crea un archivo con quince números. Además, ./times | wc -l genera 15 , lo que confirma el resultado anterior. Corriendo ./times | cat , vuelvo a ver quince números, más de cinco de los cuales son distintos .

¿Alguien sabe qué diablos puede causar algo como esto? Estoy fuera de las ideas.

./times != ./times | cat Wat.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

conocimiento previo

  • Dato 1 : cuando la salida estándar está conectada a un TTY, tiene un búfer de línea. Cuando está conectado a un archivo o a una canalización, está completamente almacenado en búfer. Esto significa que solo se vacía cada 8 KB, digamos , en lugar de cada línea.

  • Hecho 2 : los procesos bifurcados tienen copias duplicadas de los datos en memoria. Esto incluye los búferes de salida de stdio si los datos aún no se han vaciado.

  • Hecho 3 : llamar a exit() hace que los búferes de salida de stdio se vacíen antes de que finalice el programa.

Caso 1: Salida a terminal

Cuando su programa se imprime en la terminal, su salida se almacena en línea. Cada llamada a printf() que termina con \n se imprime inmediatamente. Esto significa que cada línea se imprime y el búfer de salida en memoria se vacía antes de que se ejecute fork() .

Resultado : 5 líneas de salida.

Caso 2: salida a canalización o archivo

Cuando libc ve que stdout no está conectado a un TTY, cambia a una estrategia de almacenamiento en búfer completo más eficiente. Esto hace que la salida se almacene en búfer hasta que se hayan acumulado 4 KB. Eso significa que la salida de printf() s se guarda en la memoria y las llamadas a write() se posponen.

 if (!fork()) exit(0);

Después de la bifurcación, el proceso secundario tiene una copia de la salida almacenada en búfer. La llamada exit() luego hace que ese búfer se vacíe. Sin embargo, esto no afecta el proceso principal. Su salida aún está almacenada en búfer .

Luego, cuando se imprime la segunda línea de salida, tiene dos líneas almacenadas en búfer. El siguiente proceso secundario bifurca, sale e imprime esas dos líneas. El padre conserva sus dos líneas de salida, y así sucesivamente.

Resultado: el niño procesa la impresión de 0, 1, 2, 3 y 4 líneas de salida. El programa principal imprime 5 cuando finalmente sale y vacía su salida. 0 + 1 + 2 + 3 + 4 + 5 = 15. ¡15 líneas de salida en lugar de 5!

Soluciones

  1. Llame _Exit() en lugar de exit() . La función _Exit() es como exit() , pero no llama a ninguna función registrada con atexit() . Esta sería mi solución preferida.

  2. Establecer explícitamente stdout para que se búfer de línea: setvbuf(stdout, NULL, _IOLBF, 0);

  3. Llame fflush(stdout) después de cada printf .

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda