¡Hola, jef@!
Me encanta tu problema. Es interesante. No difícil, pero sí interesante.
Un consejo, de cara al futuro, utiliza las etiquetas dedicadas a introducir código, [ code=LENGUAJEDEPROGRAMACION ][ /code ], el código será mucho más legible desde el foro. También sería útil decir en qué falla. ¿No compila? ¿El resultado no es correcto? De todas formas, tu forma de explicar el problema ha sido suficientemente clara como para poder ayudar. Asumo que programas en un entorno Linux (por la inclusión de unistd, más que nada
).
Tu forma de plantearte la solución es la correcta. De todas formas, la concurrencia del programa es "débil", porque el padre ha de esperar mientras el hijo hace faena. Y lo que si que no entiendo es que por lo que dices, tu programa no tiene entrada de datos por parte del usuario, así que no sé por que motivo haces scanf en varios puntos de tu código. Tampoco sé por qué usas dos pipes, si la comunicación es unilateral (el hijo comunica datos al padre, pero no al revés).
Continúo. Si no vas a leer el estado de finalización de un hijo, puedes hacer wait(NULL) (es preferible a declarar una variable que no vas a utilizar). El formato de salida que utilizas tampoco es el que indicas (HIJO: fibonacci % N =%M\n)...
Ahora me voy a cenar. En un rato vengo y me pongo con esto otra vez
EI: juntando mensajes.
Ya estoy aquí.
Uno de tus fallo es que no inicializas bien los arrays. Utilizas la función scanf, pero eso es para entrar datos del usuario. Si quieres que la posición x de un array tenga el valor y, haces array[ x ] = y. Además, tan pronto como sepas que no vas a usar un canal CIÉRRALO. ¿Sabes lo que es un abrazo mortal? No, no es un achuchón de estos que hacen que se te salten los ojos. Se le llama abrazo mortal a la situación en que un proceso A espera a que finalice otro proceso B, y el proceso B a su vez espera que finalice A. Evidentemente, de esta manera no acabarán nunca. Bueno, pues si no cierras canales, te expones a que suceda algo así. Es por eso que conviene abrir el menor número de pipes posible (y en este caso, te aseguro que sólo hace falta una, sólo se necesitan 2 cuando se requiere comunicación bilateral).
Por otro lado, le pasas mal el tercer parámetro tanto al write como al read. Ten en cuenta que el tercer parámetro es el número de bytes a escribir/leer. Aunque depende de la máquina, un int suele tener ser de 4 bytes (pero depende del procesador, de la implementación del compilador...). Para asegurarte el tiro y ganar en portabilidad, en vez de utilizar el valor 4 para enteros usa sizeof(int). Sizeof() es un operador que te devuelve el número de bytes que conforman cierto objeto o tipo de dato. Además, para ahorrar llamadas al sistema, puedes escribir en la pipe dos enteros de una tacada haciendo write(fdpipe[1],&tabla[8],2*sizeof(int)). De esta manera, escribes en la pipe tanto el valor de la posición 8 de tabla como de la posición 9.
Y aquí van dos errores más. Tanto en write como en read se utilizan punteros. Tu usas tabla[9] y tabla[10], y esto está mal (tabla[9] es un entero, y tú lo que tienes que hacer es pasarle el puntero a ese entero). La función read/write tratará de desreferenciar lo que le hayas pasado como parámetro, y si le pasas tabla[9] (que por poner algo, digamos que vale 10), intentará escribir/leer en/de la posición 10 de memoria. El segundo error es que no has tenido en cuenta que los índices de los vectores empiezan en el 0 a la hora de intentar pasarle al padre el noveno y décimo números de Fibonacci. Si quieres poner 10 números de Fibonacci en una tabla, el primero estará en la posición 0 y el décimo en la posición 9. Así, si quieres pasarle los números de Fibonacci 9 y 10 tienes que pasarle tabla[8] y tabla[9].
Bueno, te paso el código que he hecho yo para este problema, por si quieres tener algún ejemplo.
Le he pasado toda la tabla al padre, aunque no hiciera falta. Así puedes comprobar que no hace falta una decena de pipes y una decena de líneas para pasar 10 valores. Se puede hacer así de fácil.
No he hecho comprobación de errores (por ejemplo, no he tenido en cuenta que el fork puede fallar y que el read puede leer menos bytes de los que le índico). Para ello se puede incluir errno (para, en caso de error, informar al usuario acerca del error exacto) e incluir unas cuantas líneas con mandangas para asegurarnos de que el programa no continúa si algo falla.
En fin, espero haberte ayudado y que hayas entendido todo lo que te he explicado.
¡Saludos!
EDITO: Casi se me olvida. ¿Por qué defines una macro si despues no la usas? Me refiero a #define N=10 (que por cierto, se debería escribir #define N 10, en la definición de macros no va el signo igual).
Me encanta tu problema. Es interesante. No difícil, pero sí interesante.
Un consejo, de cara al futuro, utiliza las etiquetas dedicadas a introducir código, [ code=LENGUAJEDEPROGRAMACION ][ /code ], el código será mucho más legible desde el foro. También sería útil decir en qué falla. ¿No compila? ¿El resultado no es correcto? De todas formas, tu forma de explicar el problema ha sido suficientemente clara como para poder ayudar. Asumo que programas en un entorno Linux (por la inclusión de unistd, más que nada

Tu forma de plantearte la solución es la correcta. De todas formas, la concurrencia del programa es "débil", porque el padre ha de esperar mientras el hijo hace faena. Y lo que si que no entiendo es que por lo que dices, tu programa no tiene entrada de datos por parte del usuario, así que no sé por que motivo haces scanf en varios puntos de tu código. Tampoco sé por qué usas dos pipes, si la comunicación es unilateral (el hijo comunica datos al padre, pero no al revés).
Continúo. Si no vas a leer el estado de finalización de un hijo, puedes hacer wait(NULL) (es preferible a declarar una variable que no vas a utilizar). El formato de salida que utilizas tampoco es el que indicas (HIJO: fibonacci % N =%M\n)...
Ahora me voy a cenar. En un rato vengo y me pongo con esto otra vez

EI: juntando mensajes.
Ya estoy aquí.
Uno de tus fallo es que no inicializas bien los arrays. Utilizas la función scanf, pero eso es para entrar datos del usuario. Si quieres que la posición x de un array tenga el valor y, haces array[ x ] = y. Además, tan pronto como sepas que no vas a usar un canal CIÉRRALO. ¿Sabes lo que es un abrazo mortal? No, no es un achuchón de estos que hacen que se te salten los ojos. Se le llama abrazo mortal a la situación en que un proceso A espera a que finalice otro proceso B, y el proceso B a su vez espera que finalice A. Evidentemente, de esta manera no acabarán nunca. Bueno, pues si no cierras canales, te expones a que suceda algo así. Es por eso que conviene abrir el menor número de pipes posible (y en este caso, te aseguro que sólo hace falta una, sólo se necesitan 2 cuando se requiere comunicación bilateral).
Por otro lado, le pasas mal el tercer parámetro tanto al write como al read. Ten en cuenta que el tercer parámetro es el número de bytes a escribir/leer. Aunque depende de la máquina, un int suele tener ser de 4 bytes (pero depende del procesador, de la implementación del compilador...). Para asegurarte el tiro y ganar en portabilidad, en vez de utilizar el valor 4 para enteros usa sizeof(int). Sizeof() es un operador que te devuelve el número de bytes que conforman cierto objeto o tipo de dato. Además, para ahorrar llamadas al sistema, puedes escribir en la pipe dos enteros de una tacada haciendo write(fdpipe[1],&tabla[8],2*sizeof(int)). De esta manera, escribes en la pipe tanto el valor de la posición 8 de tabla como de la posición 9.
Y aquí van dos errores más. Tanto en write como en read se utilizan punteros. Tu usas tabla[9] y tabla[10], y esto está mal (tabla[9] es un entero, y tú lo que tienes que hacer es pasarle el puntero a ese entero). La función read/write tratará de desreferenciar lo que le hayas pasado como parámetro, y si le pasas tabla[9] (que por poner algo, digamos que vale 10), intentará escribir/leer en/de la posición 10 de memoria. El segundo error es que no has tenido en cuenta que los índices de los vectores empiezan en el 0 a la hora de intentar pasarle al padre el noveno y décimo números de Fibonacci. Si quieres poner 10 números de Fibonacci en una tabla, el primero estará en la posición 0 y el décimo en la posición 9. Así, si quieres pasarle los números de Fibonacci 9 y 10 tienes que pasarle tabla[8] y tabla[9].
Bueno, te paso el código que he hecho yo para este problema, por si quieres tener algún ejemplo.
Código (c) [Seleccionar]
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
void addTenFib(int* vector, int start) {
int i;
if (start == 0) {
vector[0] = vector[1] = 1;
i = 2;
}
else i = start;
while (i < start + 10) {
vector[i] = vector[i-1] + vector[i - 2];
++i;
}
}
int main () {
int tabla[20];
int fdpipe[2];
int i;
pipe(fdpipe);
if (fork() == 0) {
close(fdpipe[0]);
addTenFib(tabla,0);
for (i = 0; i < 10; ++i)
printf("HIJO: fibonacci %d: %d\n",i+1,tabla[i]);
write(fdpipe[1],tabla,10*sizeof(int));
exit(0);
}
close(fdpipe[1]);
wait(NULL);
read(fdpipe[0],tabla,10*sizeof(int));
close(fdpipe[0]);
addTenFib(tabla,10);
for (i = 10; i < 20; ++i)
printf("PADRE: fibonacci %d: %d\n",i+1,tabla[i]);
return 0;
}
Le he pasado toda la tabla al padre, aunque no hiciera falta. Así puedes comprobar que no hace falta una decena de pipes y una decena de líneas para pasar 10 valores. Se puede hacer así de fácil.
No he hecho comprobación de errores (por ejemplo, no he tenido en cuenta que el fork puede fallar y que el read puede leer menos bytes de los que le índico). Para ello se puede incluir errno (para, en caso de error, informar al usuario acerca del error exacto) e incluir unas cuantas líneas con mandangas para asegurarnos de que el programa no continúa si algo falla.
En fin, espero haberte ayudado y que hayas entendido todo lo que te he explicado.
¡Saludos!
EDITO: Casi se me olvida. ¿Por qué defines una macro si despues no la usas? Me refiero a #define N=10 (que por cierto, se debería escribir #define N 10, en la definición de macros no va el signo igual).