【问题标题】:What to use to signal "select" internally?用什么在内部发出“选择”信号?
【发布时间】:2021-02-20 15:21:00
【问题描述】:

我正在设计一个在 Linux 上运行的机器人,我想从运行在 TCP/IP 上的机器人获得一个仅遥测接口,主要用于我自己关于 TCP 的教育,但也用于保证数据包排序和校验和。我目前的设计是三个线程:

  1. 侦听连接并向the list 添加新连接的线程
  2. 从系统其他部分收集遥测数据并将其发送到the list 中的每个连接的线程
  3. selectthe list 关联,并删除与列表断开连接的所有客户端

我希望线程 1 能够向线程 3 发出信号“嘿伙计,新连接,更新您的列表”,对我来说显而易见的答案是创建一些可以添加到 @ 的额外文件/管道987654327@ 的select 列表,如果附加文件是通知更新列表的文件。我认为文件或管道对于信号来说有点矫枉过正,我应该认为二进制信号量可以解决问题,但我不知道如何在二进制信号量上select

我想我的问题是:你认为什么可以变成文件描述符以便你可以选择它们?

我的第二个问题是:我是一名“老派”的 Linux/C 开发人员,试图跟上更现代的技术,特别是现代 c++,是否有更“现代的 c++”方法来做到这一点?

【问题讨论】:

  • 我认为管道或套接字是您想要用于向 select() 发送信号的东西。
  • Linux 为此提供了eventfd()。你的线程 2 和 3 应该是一个线程。线程 1 可能也可以合并到其中。
  • 现代 C++ 会使用 asio 之类的。
  • 你应该合并线程 1 和 3。没有理由将它们分开。

标签: linux multithreading sockets embedded-linux


【解决方案1】:

eventfd(2) 是一个方便的特定于 Linux 的 API,用于此类通知。它创建一个文件描述符,可用于通过写入来发出事件信号。

使用它的例子(和poll(),通常比select()更可取):

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <thread>

#include <unistd.h>
#include <poll.h>
#include <sys/eventfd.h>

void messenger(int efd) {
  while (1) {
    std::uint64_t i = 1;
    if (write(efd, &i, sizeof i) != sizeof i) {
      std::perror("write");
      std::exit(1);
    }
    sleep(1);
  }
}

int main() {
  int efd = eventfd(0, 0);
  if (efd < 0) {
    std::perror("eventfd");
    return 1;
  }
  std::thread messenger_thread{messenger, efd};
  struct pollfd waiter[1];

  waiter[0].fd = efd;
  waiter[0].events = POLLIN;
  
  while (poll(waiter, 1, -1) >= 0) {
    if (waiter[0].revents & POLLIN) {
      std::uint64_t i;
      if (read(efd, &i, sizeof i) != sizeof i) {
        std::perror("read");
        return 1;
      }
      std::puts("Signaled by messenger.");
    }
  }
}

不过,正如我之前的评论中所指出的,我认为这是错误的架构——你真的不应该有另一个线程来检测关闭的连接,因为这些通常是通过套接字上的读取或写入失败发出信号的——它是最好在向他们发送数据的同一线程中完成。并且很容易拥有一个非阻塞侦听套接字,您还可以轮询它并在可读时使用accept() - 基本上,在一个线程中完成所有事情而不是尝试拆分它更容易。 收集您的机器人遥测数据可能适合单独的线程。或者它可以在处理最终接收数据的客户端的同一台中完成。你没有提供足够的信息来真正说出来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-28
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    • 2015-06-06
    • 1970-01-01
    相关资源
    最近更新 更多