c - I risultati di printf() e system() sono nell'ordine sbagliato quando l'output viene reindirizzato a un file




linux child-process (2)

È correlato al buffering dell'output. Sono riuscito a riprodurre lo stesso comportamento. Forzare il flush lo ha fatto per me.

#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;
}

Prima di aggiungere il fflush:

$ ./main > foo
$ cat foo
main
main.c
this is a test message.

e dopo:

$ ./main > foo
$ cat foo
this is a test message.
foo
main
main.c

Ho un programma C che si compila in un eseguibile chiamato myprogram. Questa è la sua funzione principale:

int main(int argc, char ** argv) {
  printf("this is a test message.\n");
  system("ls");

  return 0;
}

Quando myprogram > output.txt in una shell Linux e quindi esamino output.txt, vedo l'output di ls sopra elencato "questo è un messaggio di prova".

Sento che dovrebbe essere il contrario. Perché sta succedendo e cosa posso fare in modo che "questo sia un messaggio di prova" appaia nella parte superiore di output.txt?

Se è importante, sono nuovo sia in C che nella riga di comando.


Per impostazione predefinita, l'output su stdout è bufferizzato quando è collegato a un terminale. Cioè, il buffer viene scaricato quando è pieno o quando si aggiunge una nuova riga.

Tuttavia , se stdout non è collegato a un terminale, come quello che succede quando si reindirizza l'output dal programma su un file, allora stdout diventa completamente buffer . Ciò significa che il buffer verrà scaricato e effettivamente scritto o quando è pieno o quando viene scaricato esplicitamente (cosa che succede quando il programma esce).

Ciò significa che l'output di un processo separato avviato dal codice (come quello che succede quando si chiama il system ) verrà probabilmente scritto per primo, poiché il buffer di quel processo verrà scaricato quando termina quel processo, che è prima del proprio processo.

Cosa succede quando si utilizza il reindirizzamento (o pipe per quella materia):

  1. La tua chiamata printf scrive nel buffer stdout .
  2. La funzione di system avvia un nuovo processo, che scrive nel proprio buffer.
  3. Quando il processo esterno (avviato dalla chiamata di system ) termina, il suo buffer viene scaricato e scritto. Il tuo buffer nel tuo processo, non viene toccato.
  4. Il tuo processo termina e il buffer stdout viene scaricato e scritto.

Per ottenere l'output nell'ordine "corretto" (o almeno previsto), chiamare fflush prima di chiamare il system , per fflush esplicitamente stdout o chiamare setbuf prima di qualsiasi output per disabilitare completamente il buffering.







io-redirection