【问题标题】:Why does errno set EAGAIN if I use O_NDELAY? read from dev/tty如果我使用 O_NDELAY,为什么 errno 会设置 EAGAIN?从 dev/tty 读取
【发布时间】:2013-03-10 08:09:21
【问题描述】:

我有这个:

//...
      if ((tty = open("/dev/tty",O_RDONLY | O_NDELAY) ) == -1 )
        {
                perror("/dev/tty");
                return 1;
        }
        //...
        if (-1 == (fi = open(argv[1], O_RDONLY)) )
        {
                perror(argv[1]);
                return 1;
        }
        //...
        while (1)
        {
                printf("you have five seconds to enter a line number %d", line); 
                sleep(5);
                i = read(tty, buf, 257);
                printf("read %d\n", i);
                if ( i == -1) {
                        perror("dev/tty/"); 
                        // if nothing was entered read always returns -1
                        //and perror prints: Resource temporarily unavailable. it's STRANGE!!!
                }
                if ( i == 0 )
                {
                        lseek(fi, 0, SEEK_SET);
                        while((i = read(fi, buf, BUFSIZ)) > 0) 
                              write(1, buf, i);
                        return 0;
                }
                //...
                if ( 0 == read(fi, buf, lines_length[line]))
                {
                        fprintf(stderr,"can't read\n");
                        return 1;
                }
                write(1, buf, lines_length[line]);
        }
 //...

所以我用 O_NDELAY 标志打开 /dev/tty,但它似乎有问题,因为稍后读取返回 -1(它必须返回 0)。我不知道出了什么问题。 还有一个问题:为什么 printf("you have 5 sec")write(1, buf,lines_length[line]);

之后打印

【问题讨论】:

    标签: c unix system-calls


    【解决方案1】:

    如果没有输入 read 总是返回 -1 并且 perror 打印: 资源暂时不可用。好奇怪!!!

    这正是O_NDELAY 应该做的。它不会等待读取操作完成。如果不能立即执行,则返回-1 并设置errno = EAGAIN,而不是阻塞。


    至于你的第二个问题,你没有刷新输出。试试:fflush(stdout)

    【讨论】:

    • 对于终端也可以吗?
    • @greensher 当你传递O_NDELAY open 尝试使描述符非阻塞,而不考虑它打开的对象类型。某些对象类型可能不支持非阻塞操作 - 从您的示例来看,ttys 似乎支持。
    • @greensher 没错,我在想EAGAIN,然后输入EINTR,对不起。
    • @greensher 给我们一个更好的视角。你想达到什么目的?为什么你首先通过O_NDELAY
    • 我的大学课程的操作系统教程(教科书)说使用终端:“Если не будет ввода, то функции read(2) вернется с нулем。” (如果没有输入,则 read 返回 0);那么你能给我一个读取返回 -1 的证明吗?
    【解决方案2】:

    在早期版本的 UNIX 系统中,用于非阻塞操作的标志是 O_NDELAY。如果设置了 O_NDELAY,则 read 返回 0。由于它与 Unix 约定相矛盾(返回 0 表示文件结束),POSIX.1 定义了非阻塞模式的标志 - O_NONBLOCK。现在标志 O_NDELAY 仅用于兼容性,不应在现代应用程序中使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多