En Linux, ¿por qué esto imprime 0 y se bloquea en lugar de imprimir 0 hasta 999?
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { int n = 1000; int fromparent[2]; int fromchild[2]; int *x = 0; pipe(fromparent); pipe(fromchild); if (fork() == 0) { /* child */ while (1) { read(fromparent[0], x, 1); write(fromchild[1], x, 1); } } else { /* parent */ for (int i = 0; i < n; i++) { printf("%d\n", i); write(fromparent[1], x, 1); read(fromchild[0], x, 1); } exit(0); } }El problema es simple: pasa un puntero nulo para read y write .
Cambie la definición de x de int *x = 0; para:
char x[1] = { 0 };Como se publicó, el comportamiento es algo contradictorio:
pasar un puntero nulo para write hace que devuelva -1 inmediatamente, configurando errno en EINVAL .
por el contrario, pasar un puntero nulo a read hace que espere la entrada y solo devuelva -1 y establezca errno en EINVAL una vez que la entrada esté disponible. Esto provoca que ambos procesos se bloqueen en las llamadas de read .
Aquí hay una prueba simple para ilustrar este comportamiento:
#include <errno.h> #include <stdio.h> #include <unistd.h> int main() { int n; errno = 0; n = read(0, NULL, 1); printf("n=%d, errno=%d\n", n, errno); return 0; } Este programa espera la entrada si se ejecuta desde la consola e imprime n=-1, errno=14 después de que el usuario presiona enter .
Por el contrario, imprime n=0, errno=0 cuando la entrada estándar se redirige desde /dev/null .