使用poll()在命名管道上使用O_RDWR

使用poll()在命名管道上使用O_RDWR,第1张

使用poll()在命名管道上使用O_RDWR

首先,一些预备:

使用

O_NONBLOCK
poll()
是常见做法-并非相反。要顺利进行,您需要确保处理所有
poll()
read()
正确的返回状态:

  • read()``0
    均值EOF的返回值-另一端已关闭其连接。(通常,但不是在所有 *** 作系统上)这对应于
    poll()
    返回
    POLLHUP
    清除。您可能想
    POLLHUP
    在尝试之前进行检查
    read()
    ,但这并不是绝对必要的,因为
    read()
    可以保证
    0
    在书写侧关闭后返回。
  • 如您所知
    read()
    ,如果您在作家连接之前打电话,并且您有
    O_RDonLY | O_NONBLOCK
    ,您将反复得到EOF(
    read()
    返回
    0
    )。但是,如果您习惯在调用之前
    poll()
    等待
    POLLIN
    事件
    read()
    ,它将等待编写器连接,而不产生EOF。
  • read()
    返回值
    -1
    通常表示错误。但是,如果是
    errno == EAGAIN
    ,这仅表示当前没有更多数据可用,并且您没有阻塞,因此可以返回到
    poll()
    其他设备需要处理的情况。如果
    errno == EINTR
    ,则
    read()
    在读取任何数据之前已中断,您可以返回
    poll()
    或直接
    read()
    再次调用。

现在,对于Linux:

  • 如果您使用来打开阅读侧

    O_RDONLY
    ,则:

    • open()
      将阻塞,直到有相应的作家开放。
    • poll()
      将给予
      POLLIN
      当数据准备好被读取,或出现EOF时r事件。
    • read()
      将一直阻塞,直到读取请求的字节数,关闭连接(返回0),被信号中断或发生致命的IO错误为止。这种阻碍性的破坏了使用的目的
      poll()
      ,这就是为什么
      poll()
      几乎总是与一起使用的原因
      O_NONBLOCK
      。您可以使用an 在超时后
      alarm()
      唤醒
      read()
      ,但这太复杂了。
    • 如果作家关闭,然后将读卡器将获得
      poll()
      POLLHUP
      r事件和
      read()
      将返回
      0
      之后下去。此时,读取器必须关闭其文件句柄并重新打开它。
  • 如果您使用来打开阅读侧

    O_RDonLY | O_NONBLOCK
    ,则:

    • open()
      不会阻止。
    • poll()
      将给予
      POLLIN
      当数据准备好被读取,或出现EOF时r事件。
      poll()
      也会阻塞,直到没有可用的编写器为止。
    • 读取所有当前可用的数据之后,如果连接仍处于打开状态,
      read()
      则将返回-1并进行设置
      errno == EAGAIN
      ,或者
      0
      如果连接器已关闭(EOF) 或尚未由写入器打开 ,则将返回-1 。如果为
      errno == EAGAIN
      ,则意味着该返回到了
      poll()
      ,因为该连接已打开但没有更多数据。当时
      errno == EINTR
      read()
      尚未读取任何字节并被信号中断,因此可以重新启动它。
    • 如果作家关闭,然后将读卡器将获得
      poll()
      POLLHUP
      r事件,并且
      read()
      将返回
      0
      之后下去。此时,阅读器必须关闭其文件句柄并重新打开它。
  • (特定于Linux :)如果您在阅读方面打开

    O_RDWR
    ,则:

    • open()
      不会阻止。
    • poll()
      将给予
      POLLIN
      当数据准备好被读取r事件。但是,对于命名管道,EOF不会引起
      POLLIN
      POLLHUP
      阻止。
    • read()
      将一直阻塞,直到读取请求的字节数,被信号中断或发生其他严重的IO错误为止。对于命名管道,它不会返回
      errno == EAGAIN
      ,甚至不会
      0
      在EOF上返回。它会一直坐在那里,直到读取了请求的确切字节数,或者直到接收到一个信号为止(在这种情况下,它将返回到目前为止已读取的字节数,或者
      errno == EINTR
      如果没有读取到字节,则返回-1并进行设置)。 。
    • 如果编写器关闭,则在另一个编写器打开命名管道的情况下,读取器也不会失去稍后读取命名管道的功能,但是读取器也不会收到任何通知。
  • (特定于Linux :)如果您在阅读方面打开

    O_RDWR | O_NONBLOCK
    ,则:

    • open()
      不会阻止。
    • poll()
      将给予
      POLLIN
      当数据准备好被读取r事件。但是,EOF不会导致
      POLLIN
      或限制
      POLLHUP
      命名管道。
    • 读取所有当前可用数据后,
      read()
      将返回
      -1
      并设置
      errno == EAGAIN
      。现在该返回到
      poll()
      等待更多数据(可能来自其他流)的时间。
    • 如果编写器关闭,则在另一个编写器打开命名管道的情况下,读取器也不会失去稍后读取命名管道的功能。连接是持久的。

如您所知,

O_RDWR
与管道一起使用不是POSIX或其他标准。

然而,由于这个问题似乎来了的时候,在Linux上的最佳途径,使“d性命名管道”的生存,即使一方关闭,并不会引起

POLLHUP
revents中或回报
0
read()
,就是用
O_RDWR| O_NONBLOCK

我看到了在Linux上处理命名管道的三种主要方法:

  1. (便携式。)不使用

    poll()
    ,并且使用单个管道:

    • open(pipe, O_RDONLY);
    • 主循环:
    • read()
      根据需要提供尽可能多的数据,可能会在
      read()
      调用时循环。
      • 如果
        read() == -1
        errno == EINTR
        ,则
        read()
        重新遍历。
      • 如果为
        read() == 0
        ,则连接已关闭,并且已接收所有数据。
  2. (可移植。)使用

    poll()
    ,并期望管道(即使是命名管道)仅打开一次,并且一旦关闭,则读取器和写入器都必须重新打开它们,从而建立新的管道:

    • open(pipe, O_RDonLY | O_NONBLOCK);
    • 主循环:
    • poll()
      对于
      POLLIN
      事件,可能一次在多个管道上。(注意:这可以防止
      read()
      在连接编写器之前获得多个EOF。)
    • read()
      根据需要提供尽可能多的数据,可能会在
      read()
      调用时循环。
      • 如果
        read() == -1
        errno == EAGAIN
        ,请返回
        poll()
        步骤。
      • 如果
        read() == -1
        errno == EINTR
        ,则
        read()
        重新遍历。
      • 如果为
        read() == 0
        ,则连接已关闭,您必须终止,或者关闭并重新打开管道。
  3. (不可移植,特定于Linux。)使用

    poll()
    ,并期望命名管道永远不会终止,并且可以多次连接和断开连接:

    • open(pipe, O_RDWR | O_NONBLOCK);
    • 主循环:
    • poll()
      对于
      POLLIN
      事件,可能一次在多个管道上。
    • read()
      根据需要提供尽可能多的数据,可能会在
      read()
      调用时循环。
      • 如果
        read() == -1
        errno == EAGAIN
        ,请返回
        poll()
        步骤。
      • 如果
        read() == -1
        errno == EINTR
        ,则
        read()
        重新遍历。
      • 如果
        read() == 0
        ,那是错误的-不应
        O_RDWR
        在命名管道上发生,而应该在
        O_RDONLY
        未命名管道上发生;它表示已关闭的管道,必须将其关闭并重新打开。如果您在同一
        poll()
        事件处理循环中混合使用命名管道和未命名管道,则可能仍需要处理这种情况。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5019042.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-15
下一篇 2022-11-15

发表评论

登录后才能评论

评论列表(0条)

保存