Newsgroup: it.comp.os.linux.development
Titolo: IPC con pipe di basso livello...

Rieccomi...
... ora alle prese con le pipe ...
( leggasi "pipe" in inglese, non in italiano... :) )
Ovviamente, c'ho il "solito" problemino...
Ho fatto un programmino che definire "idiota" è un complimento...
...ma non funziona!
Ecco:
/*creo una pipe*/
if (pipe(fd) < 0) {
	perror("\n pipe error! ");
	exit(EXIT_FAILURE);
}	
/*creo un figlio*/
if ( pid=fork() < 0 ) {
	perror("\n fork error! ");
	exit(EXIT_FAILURE);
}
else if (pid!=0) {  /*codice del padre*/
	close(fd[0]);
	write(fd[1], "Ciao", 4);	
}
else { /*codice del figlio*/
	close(fd[1]);
	n=read(fd[0], buf, DIM);
	write(STDOUT_FILENO, buf, n);
}
perchè non deve funzionare ? Mi sto avvilendo...
ah.. .l'output è nullo, ovvero non stampa na ceppa...

 ah.. .l'output è nullo, ovvero non stampa na ceppa...
perchè non parti dall'esempio di ma pipe? 
come potrai vedere ci sono delle diferenze dal tuo:
       #include <sys/wait.h>
       #include <assert.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <string.h>
       int
       main(int argc, char *argv[])
       {
           int pfd[2];
           pid_t cpid;
           char buf;
           assert(argc == 2);
           if (pipe(pfd) == -1) { perror("pipe"); exit(EXIT_FAILURE); }
           cpid = fork();
           if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); }
           if (cpid == 0) {    /* Child reads from pipe */
               close(pfd[1]);          /* Close unused write end */
               while (read(pfd[0], &buf, 1) > 0)
                   write(STDOUT_FILENO, &buf, 1);
               write(STDOUT_FILENO, "\n", 1);
               close(pfd[0]);
               _exit(EXIT_SUCCESS);
           } else {            /* Parent writes argv[1] to pipe */
               close(pfd[0]);          /* Close unused read end */
               write(pfd[1], argv[1], strlen(argv[1]));
               close(pfd[1]);          /* Reader will see EOF */
               wait(NULL);             /* Wait for child */
               exit(EXIT_SUCCESS);
           }
       }

 come potrai vedere ci sono delle diferenze dal tuo:
Dall'esempio di pipe ci sono partito...
Il codice che hai postato è chiaramente diverso dal mio... perchè fa 
un'altra cosa :)
Non voglio leggere carattere per carattere da riga di comando e poi 
stampare... voglio fare altro...
Ritornando al codice che ho postato io, è un adattamento di uno stralcio 
presente su Stevens[1];
la "versione" che c'è sul libro è:
if (pipe(fd) < 0) {
	perror("\n pipe error! ");
	exit(EXIT_FAILURE);
}
if ( pid=fork() < 0 ) {
	perror("\n fork error! ");
	exit(EXIT_FAILURE);
}
else if (pid!=0) {
	close(fd[0]);
	write(fd[1], "hello world\n", 12);	
}
else {
	close(fd[1]);
	n=read(fd[0], buf, MAXLINE);
	write(STDOUT_FILENO, buf, n);
}
exit(0);
dove nel mitico "apue.h" MAXLINE è definito 4096
(per la verità nel codice ci sono anche degli "err_sys" che ho 
sostituito con i perror e gli exit)
Ebbene, tale codice compilato non mi funziona... quale può essere il 
problema ?
--
[1] W.Richard Stevens, Stephen A. Rago - "Advanced Programming in the 
Unix Environment" - Addison Wesley

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

Il 05/06/2008 07:17 PM Alexandros
Ha scritto:

E riscrivere il codice cosi' che tra l'altro dovrebbe diventare un 
peletto piu' leggibile:
/*creo una pipe*/
if (pipe(fd) < 0) {
     perror("\n pipe error! ");
     exit(EXIT_FAILURE);
}
pid=fork();
/*creo un figlio*/
if ( pid < 0 ) {
     perror("\n fork error! ");
     exit(EXIT_FAILURE);
}
/* qui non serve l'else perche' se e' < 0 esce dal progamma*/
if ( pid != 0) {  /*codice del padre*/


 if ((pid=fork()) < 0 ) {
Ehm... funzionaaaaaaaaaaaaaaaaa :)
Ma possibile che una coppia di parentesucce piccoline faceva tutta 
quella differenza? :)
E talmente che mi sono rincuorato... che mi sono cimentato in un 
esercizietto pochino pochino più complesso:
"Scrivere un programma C che crea un figlio:
  – il padre invia al figlio 10 numeri interi casuali al 
    ritmo di uno al secondo, e poi termina;
  – il figlio riceve i numeri dal padre e li stampa sul 
    terminale;
  – il figlio termina dopo aver ricevuto il decimo 
    numero.
I due processi comunicano tramite una pipe"
Da cui:
#define MAXLINE 4096
#define DIM 999
int main (int argc, char *argv[]) {
 
	int status, fd[2], n, count=1, num;
	char buf[MAXLINE], str[DIM];
	pid_t pid;
 
	/*inizializzo il seed per rand ()*/
	srand(time(NULL));
 
	/*creo la pipe*/
	if (pipe(fd) < 0) {
		perror("\n pipe error! ");
		exit(EXIT_FAILURE);
	}
	/*creo un figlio*/
	if ( (pid=fork()) < 0) {
		perror("\n fork error! ");
		exit(EXIT_FAILURE);
	}
	else if (pid!=0) { /*codice del padre*/
 
		while (count <=10) {
			close(fd[0]);
			num=rand()%DIM;
			sprintf(str, "%d\n", num);
			write(fd[1], str, strlen(str));
			count++;
			sleep(1);
		}
		exit(EXIT_SUCCESS);
	}
	else { /*codice del figlio*/
		while (count<=10) {
			close(fd[1]);
			n=read(fd[0], buf, MAXLINE);
			write(STDOUT_FILENO, buf, n);
		}
		exit(EXIT_SUCCESS);
	}
 
	return 0;
}/*END main*/
Ed è tutto ok ;)
Grazie Giovanni, sempre puntuale :)
Ma grazie anche agli altri amici che invece di ignorare i miei post, si 
avventurano nell'aiutarmi :)
Ma... una hot-line diretta non se pò fà ? :D

  quella differenza? :)
È uno degli errori più gettonati (e non solo dai principianti)!!!


 È uno degli errori più gettonati (e non solo dai principianti)!!!
verissimo, e quando capita che per assegnare un valore ad una variabile
scrivi
pippo == 1;
e non capisci mai dove diavolo è l'errore?
shit appens !


possibile soluzione: mettere le costanti all'inizio. Quindi ad esempio:
if( 1 == pippo ) { ... }
nel caso di errore di digitazione sarà il compilatore ad avvertirti. Soluzione 
possibile invece per l'errore di Alexandros è quella di effettuare gli 
assegnamenti si una singola linea, quindi:
pid = fork();
if( 0 >= pid ) {
	...
}
HTH
-- 
SF
Games are very educational. Scrabble teaches us vocabulary, Monopoly teaches 
us cash-flow management, and Dungeons & Dragons teaches us to loot dead bodies.

 quella di effettuare gli assegnamenti si una singola linea, quindi:
Sarebbe sufficiente usare *sempre* l'opzione -Wall quando si compila e 
specialmente per la prima compilazione analizzare anche i warnings.
Nel caso specifico di "if ( pid=fork() < 0 ) {" il compilatore avverte 
con il warning:
x.c:30: warning: suggest parentheses around assignment used as truth value


 
... dando per scontato che non ci siano altre centinaia di warning :-)


 :-)
Nel qual caso sarebbe meglio studiarsi meglio il linguaggio.


 Nel qual caso sarebbe meglio studiarsi meglio il linguaggio.
può anche capitare, talvolta, che il codice ti sia affidato dopo che ci abbia 
lavorato qualcun altro.


 che ci abbia lavorato qualcun altro.
Se mi affidano del codice di qualcun altro la prima cosa che faccio è 
ripulirlo dai warning per togliermi dai piedi i potenziali errori che 
certe cattive abitudini di programmazione degli altri vi hanno lasciato.
Devo dire però che ora non capita spesso, visto che per poter 
rilasciare i sorgenti i progettisti devono sottoporli ad un controllo 
con un tool (Flexelint) che verifica la qualità del codice - 
http://www.gimpel.com/
 .
