【问题标题】:Why doesn't this print 0 through 999?为什么不打印 0 到 999?
【发布时间】:2022-01-07 15:48:45
【问题描述】:

在 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);
    }
}

【问题讨论】:

  • 注意:如果失败,fork() 的返回值可以是-1。你对这个案子处理不当。

标签: c linux pipe posix


【解决方案1】:

问题很简单:将空指针传递给readwrite

x的定义从int *x = 0;改为:

char x[1] = { 0 };

正如发布的那样,这种行为有点违反直觉:

  • 将空指针传递给write 会导致它立即返回-1,将errno 设置为EINVAL

  • 相反,将空指针传递给read 会导致它等待输入,并且只有在输入可用时才返回-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

【讨论】:

  • 或者char x[1] = { 0 };
  • @SteveSummit:好点子,尽管在这种特殊情况下并不重要,因为x 的内容实际上并没有被使用。
  • 等等......这不应该导致它快速循环,因为 read 只会设置 EINVAL 或类似的东西吗?
  • @Joshua:有趣的评论:write 是这样,但read 不是。查看更新的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多