简体   繁体   English

用什么来在内部发出“选择”信号?

[英]What to use to signal "select" internally?

I am designing a robot that runs on Linux, I want to have a telemetry only interface from the robot that runs on TCP/IP mostly for my own education about TCP but also for guaranteed packet ordering and the checksum.我正在设计一个在 Linux 上运行的机器人,我希望有一个来自机器人的仅遥测接口,该接口在 TCP/IP 上运行,主要用于我自己关于 TCP 的教育,但也用于保证数据包排序和校验和。 My current design is to have three threads:我目前的设计是有三个线程:

  1. Thread that listens for connections and adds new connections to the list侦听连接并将新连接添加到the list线程
  2. Thread that collects the telemetry from the other parts of the system and sends it to each connection in the list从系统的其他部分收集遥测数据并将其发送到the list每个连接的线程
  3. Thread that select 's on the list and removes any clients that disconnect from the list select 's on the list并删除所有与列表断开连接的客户端的线程

I'd like thread 1 to be able to signal thread 3 "Hey buddy, new connection, update your list", the obvious answer to me is create some additional file/pipe that can be added to 3 's select list and if the additional file is the one signaled update the list.我希望线程1能够向线程3发出信号“嘿,伙计,新连接,更新您的列表”,对我来说显而易见的答案是创建一些可以添加到3select列表中的附加文件/管道,如果附加文件是通知更新列表的文件。 I think a file or a pipe is bit of overkill for signaling though,I should think a binary semaphore would do the trick, but I don't know how to select on a binary semaphore.我认为文件或管道对于信号量来说有点矫枉过正,我应该认为二进制信号量可以解决问题,但我不知道如何select二进制信号量。

I guess my question is: what thinks can you turn into a file descriptor so you can select on them?我想我的问题是:你认为可以变成文件描述符以便您可以选择它们吗?

My secondary question is: I am a "older school" Linux/C developer trying to come up to speed on more modern techniques, specifically modern c++, is there a more "modern c++" way to do this?我的第二个问题是:我是一个“老派”的 Linux/C 开发人员,试图跟上更现代的技术,特别是现代 C++,有没有更“现代 C++”的方法来做到这一点?

eventfd(2) is a handy Linux-specific API that is meant for this sort of notification. eventfd(2)是一个方便的 Linux 特定 API,用于此类通知。 It creates a file descriptor that can be used to signal events by writing to it.它创建了一个文件描述符,可用于通过写入来发送事件信号。

Example using it (And poll() , which is generally preferable to select() ):使用它的示例(和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.");
    }
  }
}

As noted in my earlier comment, though, I think this is the wrong architecture - you really shouldn't have another thread just to detect closed connections, as those are generally signaled via a failed read or write on the socket - it's best done in the same thread that's sending data to them.但是,正如我之前的评论中所指出的,我认为这是错误的架构 - 你真的不应该有另一个线程来检测关闭的连接,因为这些通常是通过对套接字的读取或写入失败发出信号的 - 最好在向他们发送数据的同一个线程。 And it's easy to have a non-blocking listening socket that you also poll for and accept() when readable - basically, it's easier to do everything in one thread instead of trying to split it up.并且很容易拥有一个非阻塞侦听套接字,您也可以在可读时轮询和accept() - 基本上,在一个线程中完成所有事情而不是尝试拆分它更容易。 Collecting the data from your robot telemetry might be suitable for a separate thread, though.不过,从您的机器人遥测收集数据可能适用于单独的线程。 Or it could be done in the same one that handles the clients that end up receiving the data.或者它可以在处理最终接收数据的客户端的同一个中完成。 You don't give enough information to really say.你没有提供足够的信息来真正说出来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM