De Sagolpan y Satan (0.125 ptos.): usan una sola tubería
para "hablar" con
los hijos. El precio que hay que pagar es que el padre
tiene un hijo,
habla con él y espera a que muera.
Así es como logramos que otro hijo no se adelante y lea
lo que no le corresponda (problema de sincronización).
#define _HPUX_SOURCE
#include <sys/ipc.h>
#include <stdio.h>
int main(void)
{
int tuberia[2], hijos, devuelto;
char cadena[2];
if(pipe(tuberia)==-1)
{
perror("pipe");
return -1; /* ¡¡¡QUE NO!!! Al S.O. se le devuelve algo ≥ 0 */
}
for(hijos = 1; hijos <= 10; hijos++)
{
switch(fork()) {
case -1: perror("fork");
return -1; /* ¡¡¡QUE NO!!! Al S.O. se le devuelve algo ≥ 0 */
case 0: if(read(tuberia[0], cadena, 2) == -1)
{
perror("read");
return -1; /* ¡¡¡QUE NO!!! Al S.O. se le devuelve algo ≥ 0 */
}
fprintf(stdout, "Soy el hijo %s y mi PID es %d.\n",
cadena, getpid());
return 0;
default: sprintf(cadena, "%d", hijos);
if(write(tuberia[1], cadena, 2) == -1)
{
perror("write");
return -1; /* ¡¡¡QUE NO!!! Al S.O. se le devuelve algo ≥ 0 */
}
wait(&devuelto); /* La madre del cordero. */
}
}
return 0;
}
De Goku y Son Gohan (0.125 ptos.): usan una tubería diferente para cada hijo.
Así no hace falta sincronizar. La espera se produce al final.
Esta fue mi idea original.
#define _HPUX_SOURCE
#define NUM_HIJOS 10
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void hijo(void);
int tuberia[2]; /* ¡¡¡OJO!!! Variable global innecesaria */
int main(int argc,char *argv[])
{
int i,retorno,todos=1;
if(argc!=1)
{
fprintf(stderr,"Uso: %s\n\n",argv[0]);
return 1;
}
if(pipe(tuberia)==-1)
{
perror("pract7-1:pipe");
return 2;
}
for(i=1;<=NUM_HIJOS;i++)
{
switch(fork())
{
case -1:
perror("pract7-1:fork");
return 3;
case 0:
hijo();
default:
if(write(tuberia[1],&i,sizeof(int))==-1)
{ /* Pasan los datos en binario (frente ASCII). Comparad con arriba. */
perror("pract7-1:write");
return 4;
}
}
}
for(i=1;i<=NUM_HIJOS;i++)
{
if(wait(&retorno)==-1)
{
perror("pract7-1:wait");
return 5;
}
if(WIFEXITED(retorno))
if(WEXITSTATUS(retorno)!=0)
{
printf("El hijo numero %d ha tenido un error.\n",i);
todos=0;
}
}
if(todos)
printf("\n Todos mis hijos han acabado sin errores\n");
close(tuberia[0]); /* ¡Bien! Las tuberías también se cierran. */
close(tuberia[1]); /* Aquí da un poco igual, pues el proceso va a morir. */
return 0;
}
void hijo(void)
{
int pid,num_hijo;
if(read(tuberia[0],&num_hijo,sizeof(int))==-1)
{
perror("pract7-1:read");
exit(6);
}
if(num_hijo==1)
if(system("clear")==-1)
{
perror("pract-1:system");
exit(7);
}
pid=getpid();
if(pid==-1)
{
perror("pract7-1:getpid");
exit(8);
}
printf("\n Soy el numero de hijo %d y mi pid es %d \n",num_hijo,pid);
close(tuberia[0]);
close(tuberia[1]);
exit(0);
}