Newsgroup: it.comp.os.linux.development
Titolo: echo di bash VS  NONSO del C

allora sto facendo uno script che prende l'out di un mio programma in C e
li pipa dentro un gauge dialog
il problema č questo se dal programma faccio delle system ("echo
blabla"), il dialog ne accetta correttamente l'output , se invece utilizzo
delle printf il comportamento č completamente sballato, e non riesco a
capirne il perchč..
esempio:
queso funziona:
while(perc < 100)
{
	system("echo \"XXX\"");
	system("echo \"Copia dei file in corso.....\"");
	system("echo \"XXX\"");
	sprintf(comando,"echo \"%d\"",perc);
	system(comando);
	perc++;
	usleep(500000);
}
mentre questo non va , ed ho provato varie forme del printf tipo:
printf("\"XXX\"\n");
printf("XXX\r\n");
e tutte le loro possibili combinazioni
while(1)
{
	printf("XXX\n");
	printf("Copia dei file in corso.....\n");
	printf("XXX\n");
	printf("%d\n",perc);
	usleep(500000)
}
ecco dopo che questo ciclo č terminato riesco a vedere quella che doveva
essere l'ultima schermata del dialog, ma di quelle intermedie niente, come
se l'out del programma arrivasse "tutto in una volta"
vi chiedo quindi, per non star a fare un milione di system, come faccio ad
emulare l'echo dal codice C?
ah, il programma (pippo.c) viene eseguito da uno script in questo modo:
./main -choice 1 | dialog --title "AGGIORNAMENTO VIDEO IKUSI" --gauge ""
10 60 0
grazie in anticipo per l'aiuto

 
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   Registered Linux user #337974  < 
http://giovanni.homelinux.net/
 >

 Mettendo una usleep() dopo ogni printf() potrebbe essere sufficiente.
Non credo che aiuti molto visto che un usleep eseguita ad ogni ciclo
dovrebbe piu' che bastare ad interrompere il processo.
Il problema dovrebbe dipendere dal fatto che non viene eseguito il
flush del buffer dello stdout se non che alla fine del programma (o al
riempimento del buffer).
In pratica le printf scrivono sul buffer dello stdout che pero' non
viene immediatamente riversato nella pipe. Quando usleep viene
chiamata, il processo viene interrotto ma la pipe continua ad essere
vuota. Cosi' si continua a ciclare fino alla fine del programma quando
finalmente viene eseguito il flush dello stdout.
Con system funziona poiche', quando il processo echo termina, viene
effettuato il flush.
Quindi dovrebbe bastare un "fflush(stdout);" prima dell'usleep.
Inoltre non ne sono sicuro ma credo che a questo punto l'usleep non
serva piu', visto che fflush interrompe il processo.
Saluti,
The Librarian

7h3.l1...@gmail.com
 wrote:

Il flush del buffer dello stdout viene fatto anche ogni volta che c'è 
'\n' alla fine della stringa.  Quindi non dovrebbe servire la fflush().
Piuttosto occorre capire quando lo scheduler attiva il processo in 
attesa sulla pipe.  In certi sistemi il processo viene schedulato solo 
quando la pipe è piena.  Mi sembra che Linux invece viene schedulato 
appena possibile, ma non ho trovato documentazione per averne la 
conferma.  In ogni caso la pipe ha un buffer di almeno 1 blocco del 
file system (4k per ext2/3).


 volta che c'è '\n' alla fine della stringa...
Davvero? Non mi risulta.


Sorry. :-(
Hai ragione.  stdout e stderr sono "line buffered" solo quando sono 
diretti ad un terminale interattivo.


> Quindi dovrebbe bastare un "fflush(stdout);" prima dell'usleep.
esatto era proprio questo, grazie mille.

 write() invece di printf() non sarebbe corretto?
Per quanto sia possibile usare la write al posto della printf, non
credo sia consigliabile visto che:
- Si deve scrivere testo sullo standard output (printf e' la soluzione
classica, usare write per questo scopo sarebbe poco ortodosso)
- L'ouput deve essere formattato (dovresti usare una sprintf + write
per ottenere lo stesso risultato)
- La write non risolverebbe il problema poiche' non  effettua
automaticamente il flush del buffer di output
Saluti,
The Librarian

 The Librarian
ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 che io sappia write(2) e read(2) NON sono bufferizzate. (Stevens docet)
Hai ragione.
Chiedo venia ma evidentemente mi sto rincretinendo prima del tempo...
Per un qualche motivo oscuro parlando della write stavo pensando alla
fwrite.
Si, la write non e' bufferizzata e risolverebbe il problema (anche se
preferisco comunque la soluzione printf + fflush).
Saluti,
The Librarian

 The Librarian
Ciao


 di IO che sarebbe comunque semplice da fare da programma.
Puoi chiarire meglio questo punto?
Io ho sempre pensato che l'I/O bufferizzato servisse per ottimizzare
le prestazioni. Tra l'altro mi pare di ricordare una discussione di
molto tempo fa (parecchi anni, a dire la verita') su comp.lang.c in
cui l'OP si meravigliava di non riuscire a superare le prestazioni in
scrittura dell'I/O bufferizzato utilizzando write e un buffer di varie
dimensioni. Anzi per alcune dimensioni del buffer otteneva prestazioni
significativamente peggiori.
Saluti,
The Librarian

 The Librarian
Do' enfasi al "Ho maturato la convinzione", nel senso che sono idee
di cui mi sono persuaso facendo delle opinabili considerazioni.
Che per fornire una libreria di IO che supporti un minimo di input
output line oriented ci voglia la bufferizzazione e' intuitivo.
Altrimenti una fgets dovrebbe iterare delle read(2) di un char,
controllare se e' un /n e se no andare avanti. Molto pesante quindi.
tuttavia chiedere a un SO di supportare nativamente l' IO per linee
e' chiedere troppo. quindi si fanno grosse letture e si forniscono
linee intere. ovviamente non si deve piu' trascendere dal buffer
per accedere allo stream perche' questi potrebbe aver letto anticipatamente
dei caratteri. Quindi a mio dire sono state fornite tutte le funzioni
di IO bufferizzato, persino fread e fwrite per IO a blocchi, per non
aver bisogno di altro.
L' ANSI C addirittura ha standardizzato solo quelle, non quelle 
native Unix.
fwrite potrebbe sembrare piu' veloce di write solo se riesce a ridurre
le write effettive, o a farle tutte alla chiusura del programma.
Certo che un programma che in diverse fasi esegue delle write anziche'
trattenere i dati in un buffer anche non gestito dalle libc e scaricarli
tutti alla fine o all riempimento del buffer puo' sembrare piu' lento, ma
e' solo una questione di progettazione. Del resto la bufferizzazione
puo' essere fatta dal programmatore stesso in modo molto semplice, senza
che le libc debbano fornire tale servizio. Per questo credo che lo scopo
sia solo fornire IO line oriented piuttosto che efficienza, che potrebbe
essere ricercata con tecnice esplicite di bufferizzazione comunque,
anziche' occulte.
A me capita spesso di reinventare l' IO bufferizzato per codice di
networking. La bufferizzazione delle libc non va d' accordo con
select(2) e quindi tutti i protocolli (HTTP, SMTP, ...) anche se
line oriented li devo acquisire per blocchi e poi ricostruire le linee
gestendo anche le "rimanenze" per non bloccare select(2).
Inoltre programmi che usano IO bufferuzzato funzionano male con pipe
bidirezionali, per questo certe versione ammettono il flag -u
per tutte le utility (sotto Linux non ne vedo, forse usano solo
unbuffered?)
