【问题标题】:sockfd in SIGINFO struct for SIGIO signalSIGINFO 结构中的 sockfd 用于 SIGIO 信号
【发布时间】:2017-06-20 12:43:05
【问题描述】:

我正在从我的应用程序中删除 boost(因为我想在使用 pre c++ 11 时摆脱 boost),作为其中的一部分,我遇到了以下问题。

我有一段代码使用 boost(async_connect、async_write 和 async_read 调用)异步连接、请求和接收来自远程服务器的数据。我打算用异步模式下运行的 linux 原生套接字替换它。

同样,我开始关注 ioctl(_sockfd, FIOASYNC, &on); 将套接字设置为异步模式。 接下来我也设置 fcntl(_sockfd, F_SETOWN, getpid()); 将所有与 sockfd 相关的信号定向到创建套接字的进程。 处理 SIGIO 信号可以访问包含各种信号相关信息的 siginfo_t 结构。

但是我无法从接收到的 siginfo 结构实例中获取 sockfd,这使得很难破译哪个 sockfd;s SIGIO 信号已被捕获。 si->si_fd 与调用 connect 的 _sockfd 不匹配。 为什么 SIGINFO for SIGIO 中的 fd 与生成此信号的 sockfd 不匹配。 siginfo的内容还靠谱吗?

【问题讨论】:

  • 我建议你忽略信号 API 并使用 select() 或 poll() 来实现你的套接字处理,信号不能很好地与多线程或面向对象的设计配合使用,如果你需要异步套接字并用 C++ 编写代码,很有可能两者都需要。
  • 您在使用 sigaction() 建立信号处理程序时是否设置了SA_SIGINFO?另见stackoverflow.com/questions/19866754/…

标签: c++ sockets asynchronous boost struct


【解决方案1】:

来自socket(7) 联机帮助页:

Signals
   ...[SIGPIPE para elided]...

   When requested with the FIOSETOWN fcntl(2) or SIOCSPGRP ioctl(2),
   SIGIO is sent when an I/O event occurs.  It is possible to use
   poll(2) or select(2) in the signal handler to find out which socket
   the event occurred on.  An alternative (in Linux 2.2) is to set a
   real-time signal using the F_SETSIG fcntl(2); the handler of the real
   time signal will be called with the file descriptor in the si_fd
   field of its siginfo_t.  See fcntl(2) for more information.

   Under some circumstances (e.g., multiple processes accessing a single
   socket), the condition that caused the SIGIO may have already
   disappeared when the process reacts to the signal.  If this happens,
   the process should wait again because Linux will resend the signal
   later.

所以,

  • 或者使用实时信号代替fcntl(sockfd, F_SETSIG, ...)
  • 在信号处理程序中使用非阻塞 pollselect 来识别触发 fd,
  • 或者,首先使用普通的同步多路复用(select/poll)。这是更正常的 IME,避免了所有令人讨厌的信号处理问题,但可能需要围绕事件循环重构整个程序,所以...

【讨论】:

    【解决方案2】:

    POSIX aio 怎么样?我个人从来没有碰巧使用过它,但也许它就是你想要的。 https://linux.die.net/man/7/aio

    还有,你为什么不喜欢boost::asioboost::threadboost::regexp 和其他一些东西在 C++11/14 中实际上是多余的,boost::filesystem 在 C++17 中是多余的。但标准库不包含asio 模拟。恕我直言,最好使用现成的、经过测试的、可移植的和广泛传播的解决方案,而不是从头开始编写自己的解决方案。

    【讨论】:

    • boost::asio 对于我的用例来说实际上很重。 Boost IOService 队列过于通用,因此有开销(每个 poll_one 的互斥锁解锁和锁定)。因此,我正在考虑摆脱它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多