为什么这不打印 0 到 999?
Why doesn't this print 0 through 999?
在 Linux 上,为什么这会打印 0
并挂起而不是打印 0 到 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);
}
}
问题很简单:你将空指针传递给 read
和 write
.
将 x
的定义从 int *x = 0;
更改为:
char x[1] = { 0 };
正如发布的那样,这种行为有点违反直觉:
将空指针传递给 write
会导致它立即变为 return -1
,将 errno
设置为 EINVAL
。
相反,将空指针传递给 read
会导致它等待输入并且仅 return -1
并将 errno
设置为 EINVAL
一旦输入可用。这导致两个进程都阻塞 read
调用。
这里有一个简单的测试来说明这种行为:
#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;
}
如果 运行 来自控制台,此程序等待输入,并在用户点击 enter 后打印 n=-1, errno=14
。
相反,当标准输入从 /dev/null
重定向时,它打印 n=0, errno=0
。
在 Linux 上,为什么这会打印 0
并挂起而不是打印 0 到 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);
}
}
问题很简单:你将空指针传递给 read
和 write
.
将 x
的定义从 int *x = 0;
更改为:
char x[1] = { 0 };
正如发布的那样,这种行为有点违反直觉:
将空指针传递给
write
会导致它立即变为 return-1
,将errno
设置为EINVAL
。相反,将空指针传递给
read
会导致它等待输入并且仅 return-1
并将errno
设置为EINVAL
一旦输入可用。这导致两个进程都阻塞read
调用。
这里有一个简单的测试来说明这种行为:
#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;
}
如果 运行 来自控制台,此程序等待输入,并在用户点击 enter 后打印 n=-1, errno=14
。
相反,当标准输入从 /dev/null
重定向时,它打印 n=0, errno=0
。