Hay dos problemas:
El primero es que no inicializas el buffer del lector antes de la
primer lectura del FIFO, por lo cual si el read trajera menos de 50
bytes lo que queda en el resto del buffer es indefinido. El printf()
va a imprimir el buffer hasta encontrar un \0. Si tuviste la suerte de
que el destino pusiera un \0 en algun lugar del buffer, tendras el
mensaje mas un poco de basura. Si no tuviste esa suerte, vas a estar
accediendo a memoria ajena :)
El segundo problema es parecido al otro pero mas sutil. Resulta que,
bajo ciertas circunstancias la concurrencia te esta jugando en contra.
El proceso escritor puede ser mucho mas rapido que el lector y
escribir mas de 50 bytes en el FIFO antes que el lector lo lea por
primera vez. Si se da ese caso (y se da) el primer read() llena el
buffer con 50 bytes, pero como el buffer *es* de 50 bytes y estas de
vuelta en el primer problema, no hay \0 final. La solucion mas facil
es que pongas un buffer de 51 bytes y el ultimo lo dejes en \0
siempre.
Saludos!
2008/10/21 San Martín, Matías <[EMAIL PROTECTED]>:
> buenas gente, a ver si alguno me puede ayudar con este problema.
> La idea es que tengo un proceso lector y uno escritor que se comunican
> mediante un FIFO. El proceso lector crea el FIFO y el escritor le manda 3
> mensajes.Despues el escritor cierra su fd y cuando el lector obtiene un 0
> como resultado del read cierra el suyo y elimina el FIFO.
> El asunto es que el lector me recibie mal los mensajes si el escritor le
> manda el \0 del final y no entiendo por que.
> No se si ayuda pero,un dato curioso es qeu dependiendo de que tamaño tenga
> el buffer de lectura (que determina en cuantas leidas recibo una cadena)
> recibo distintos mensajes.
> Si hago al escritor que no mande el \0 del final anda todo ok.
> Alguien tiene alguna pista de porque puede ser este comportamiento??
>
> Les mando el codigo por si les sirve para algo:
>
> ________________________________
>
> #include <cstdio>
> #include <cstdlib>
> #include <cstring>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <unistd.h>
> #include <fcntl.h>
> #include <errno.h>
>
> #define CANT_MAX_ESCRITORES 1//10
> #define NOMBRE_FIFO "./miPipe"
>
> #include <sys/wait.h>
>
> using namespace std;
>
> int main(int argc, char **argv) {
>
> pid_t nuevoPid = 0;
>
> //se lanzan todos los procesos desde el mismo proceso padre
> for (unsigned i = CANT_MAX_ESCRITORES; i-- && ((nuevoPid = fork()) > 0); );
>
> if (nuevoPid == -1){perror("No se pudo crear proceso\n");exit(1);}
>
> if (nuevoPid == 0)
> {//proceso hijo, escritor
>
> int fd;
> /* Si la tubería no existe cuando el proceso escritor intenta abrirla,
> * el escritor vuelve a intentarlo cada segundo hasta que pueda abrirla */
> while (((fd = open(NOMBRE_FIFO,O_WRONLY)) == -1) && (errno == ENOENT))
> sleep(1);
>
> if (fd == -1){perror("No se pudo abrir el FIFO para escritura\n");exit(1);}
>
> //se escriben los 3 mensajes en el FIFO
> const unsigned short tamBufCadena = 50;
> char cadena[tamBufCadena];
> for (unsigned short nmensaje = 1; nmensaje <= 3;nmensaje++)
> {
> memset(cadena,0,tamBufCadena);
> sprintf( cadena, "Mensaje numero %d pid: %d\n", nmensaje, getpid() );
> size_t count = strlen(cadena);// + 1; <============= ACA SI AGREGO EL +1 SE
> COMPORTA DE LA FORMA "EXTRAÑA" DICHA
> size_t escritoTotal;
> ssize_t escrito;
> escritoTotal = 0;
>
> while ((escritoTotal < count) && ((escrito = write(fd, ((char*)cadena) +
> escritoTotal,count - escritoTotal)) > 0) )
> escritoTotal += escrito;
>
> if (escrito == -1){perror("No se pudo escribir en el FIFO\n");exit(1);}
> }
>
> if (close(fd) == -1){perror("No se pudo cerrar el FIFO de
> escritura\n");exit(1);}
>
> exit(0);
> }
>
> //proceso padre, lector
>
> //se crea el FIFO con permisos los permisos adecuados
> if (mknod(NOMBRE_FIFO,S_IFIFO | 0666,0) == -1){perror("No se pudo crear el
> FIFO\n");exit(1);}
>
> int fd;
>
> if ((fd = open(NOMBRE_FIFO,O_RDONLY)) == -1){perror("No se pudo abrir el
> FIFO para lectura\n");exit(1);}
>
> ssize_t leido;
> const unsigned short count = 50; //tamaño del buffer de lectura
> char buf[count];
>
> //se lee del FIFO hasta que se cierra (devuelve 0) o hay error (devuelve -1)
> while ((leido = read(fd, buf,count)) > 0)
> {
> printf("%d: %s\n",getpid(),buf);
> memset(buf,0,count);
> }
>
> if (leido == -1){perror("No se pudo leer del FIFO\n");exit(1);}
>
> if (close(fd) == -1){perror("No se pudo cerrar el FIFO de
> lectura\n");exit(1);}
> //se elimina el fifo
> if (unlink(NOMBRE_FIFO) == -1){perror("No se pudo eliminar el
> FIFO\n");exit(1);}
> return 0;
>
> }
>
> ________________________________
>
> saludos, se agradece cualquier comentario,
> _______________________________________________
> Lista de correo Programacion.
> [email protected]
> http://listas.fi.uba.ar/mailman/listinfo/programacion
>
>
--
juanii
_______________________________________________
Lista de correo Programacion.
[email protected]
http://listas.fi.uba.ar/mailman/listinfo/programacion