我可以测试文件描述符是否是 read() 的正确类型吗? [英] Can I test if a file descriptor is of the right type for read()?

查看:41
本文介绍了我可以测试文件描述符是否是 read() 的正确类型吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有很多 fds 无法读取(例如,侦听套接字).我如何测试 fd 上的 read(2) 是否会返回 EINVAL,而不会有取出数据的风险?

There are plenty of fds that can't be read from (for example, a listening socket). How do I test whether a read(2) on the fd will return EINVAL, without risking taking data out?

  1. 我们可以执行一个 read() 并传递一个零字节缓冲区.不过,这被排除了:

  1. We could do a read() with a zero-byte buffer passed. This is ruled out though:

允许但不要求实现对零字节的 read() 请求执行错误检查.[来自 POSIX 1003.1-2008]

Implementations are allowed, but not required, to perform error checking for read() requests of zero bytes. [From POSIX 1003.1-2008]

  • 我们可能会想在描述符上调用 select().不幸的是,select() 对于可读集有非常重载的语义,所以会告诉 fd 是可读的",而实际上调用 read() 是错误的它(例如,侦听套接字将被标记为可读"但需要 accept(),而不是 read(),并且还有其他不可移植的示例,例如 event 或kqueue fds).

  • We might be tempted to call select() on the descriptor. Unfortunately, select() has very overloaded semantics for the readable set, so will tell that an fd is "readable" when in fact it's an error to call read() on it (for example, a listening socket will be marked "readable" but needs accept(), not read(), and there are other non-portable examples like event or kqueue fds).

    (作品种类)阅读您编译的每个平台的联机帮助页,使用特定的系统调用测试 fd 以生成大致如下所示的函数:

    (Sort of works) Read manpages for every platform you compile on test the fd with specific system calls to produce a function that looks roughly like:

    int isReadable(int fd)
    { return isActiveSocket(fd) || isFifo(fd) || isRegFile(fd) ||
               isEventFd(fd) || ... /* more pain */ }
    

  • (作品类型)请注意,read() 本身并不一定能很好地回答 fd 是否适合系统调用!令人惊讶的是,EINVAL 在 POSIX 中未指定用于 read()(STREAMS 除外),但在 linux 上提供给您(EINVAL:fd 附加到一个对象,该对象是不适合阅读")并且在 BSD 上相当神秘(EINVAL:与 [fd] 关联的指针为负数.").

  • (Sort of works) Note that read() itself doesn't necessarily give you a nice answer as to whether the fd was the right type for the system call! Surprisingly, EINVAL is unspecified in POSIX for read() (except on STREAMS), but is given to you on linux ("EINVAL: fd is attached to an object which is unsuitable for reading") and rather mysteriously on BSD ("EINVAL: The pointer associated with [the fd] was negative.").

    场景

    有人启动了您的应用程序,您想知道值为 0 的 fd 是否是伪造的(例如侦听套接字),或者是否可以从中读取.您希望不尝试实际的 read() a) 因为这会阻塞,b) 因为在取出数据后您无法将其填回.

    Scenarios

    Someone launches your application, and you want to know whether the fd with value 0 is bogus (eg a listening socket) or whether it's ever going to possible to read from it. You'd like to do without trying an actual read() a) because that blocks, b) because after taking the data out you can't stuff it back in.

    推荐答案

    没有.您自己引用了规范的相关部分.

    No. You quoted the relevant part of the specification yourself.

    实际上,由于多种原因,读取可能随时失败.测试将读取成功",然后是 read,只会引入竞争条件 - 两次调用之间的情况可能会发生变化.

    Indeed, a read may fail at any time for any number of reasons. Testing for "will read succeed", followed by a read, merely introduces a race condition - the situation may change in between the two calls.

    您需要以正确处理失败读取的方式编写您的应用程序.如果这样做,您通常不需要事先关心测试,只需使用 select 来确定数据何时(可能)可用.

    You need to write your application in such a way that a failed read is handled appropriately. If you do that, you won't usually need to care about testing beforehand, and can simply use select to determine when data is (probably) available.

    这篇关于我可以测试文件描述符是否是 read() 的正确类型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆