如何在 Ruby 中访问FD_SETSIZE?生成 CPP (??)

How to access FD_SETSIZE in Ruby? spawn cpp (??)

提问人:Sean Champ 提问时间:11/6/2021 最后编辑:Sean Champ 更新时间:11/6/2021 访问量:55

问:

在阅读有关 Ruby 中的 IO 的信息时,此外,在一般对 POSIX 友好的 libc 环境中刷新我自己对 I/O 的了解有限,我在 Stack Overflow 上发现了一个问题:rubby 中的 poll()? 这样就提出了一个问题,即研究对象。

答复中提到了 Ruby 中一种方法的可用性。然而,它也引起了对在某些条件下在某些操作系统(包括 Linux)上使用的担忧,例如,当 Ruby 进程中可能打开了 1024 个或更多的文件描述符时。selectselect

在对 ruby? 中的 poll() 问题的一些回答中,有人建议 if 在这样的环境中调用,可能会导致应用程序中的内存损坏。虽然在其他文档中,这种担忧可能没有表现出如此严重,并且可能有一种方法可以在这种情况下可移植地避免调用 - 正如后来的阅读所表明的那样 - 也许问题仍然是如何可移植地解决这个问题,对于 Ruby 的 .selectselectselect

在阅读有关它的更多信息时,我注意到 Linux 上 select(2) 手册页的 “BUGS” 部分提供了可能代表对该问题的广泛讨论的内容。文本提到了一个常量,显然表示在调用时可以打开的文件描述符数量的排他性上限,因此可能期望在那时正常执行(粗略解释)。FD_SETSIZEselectselect

引用 select(2) 手册页:

   POSIX allows an implementation to define an upper limit,
   advertised via the constant FD_SETSIZE, on the range of file
   descriptors that can be specified in a file descriptor set.  The
   Linux kernel imposes no fixed limit, but the glibc implementation
   makes fd_set a fixed-size type, with FD_SETSIZE defined as 1024,
   and the FD_*() macros operating according to that limit.  To
   monitor file descriptors greater than 1023, use poll(2) or
   epoll(7) instead.

   The implementation of the fd_set arguments as value-result
   arguments is a design error that is avoided in poll(2) and
   epoll(7).

   According to POSIX, select() should check all specified file
   descriptors in the three file descriptor sets, up to the limit
   nfds-1.  However, the current implementation ignores any file
   descriptor in these sets that is greater than the maximum file
   descriptor number that the process currently has open.  According
   to POSIX, any such file descriptor that is specified in one of
   the sets should result in the error EBADF.

在 Ruby 中利用这一点,尽管可能是一种猜测:确定 Ruby 环境的最佳方法是什么?FD_SETSIZE

如果它作为常量可用,则假定该常量的值可以在任何打开的文件描述符上调用“select”之前在条件测试中使用。然后,Ruby 程序可能会在内部引发异常,然后调用任何等于或大于实例值的文件描述符,至少对于通常对 POSIX 友好的操作系统是这样?selectFD_SETSIZE

如果没有更简洁的方法来解决这个问题,也许可以将其用于项目的分发工具中,例如确定目标体系结构的常量值,然后将其与任何其他应用程序常量一起存储?我猜 a 可以用于此 - 无论是来自 GCC、LLVM 还是任何其他工具链 - 也许在某些方面类似于 sb-grovelcpp

也许还有其他方法可以解决这个问题,而且是便携式的?也许在 Ruby 的某个地方已经有一个常数了?

也许在 Ruby 源代码中已经有一些关于它的检查?我想现在是时候寻找那个 GitHub 存储库了......

Ruby IO Stream posix 文件描述符

评论

0赞 Casper 11/6/2021
为什么不尝试一下,看看你是否能找到一个或实现呢?无论如何,检查FD_SETSIZE很可能需要编译器。你到底想达到什么目的?你为什么问这个问题?如果目的是构建一个具有> 1024 套接字的应用程序,那么寻找实现 (gem) 不是更容易吗?pollepoll(e)poll
0赞 Sean Champ 11/6/2021
我问这个问题是为了便携性,希望它能以某种有意义的方式得到解决。在我找到的问题中,关于在 ruby 中进行民意调查的可用性,有一个回答表明至少有一个类似民意调查的界面在内部使用 select。即使在构建时使用编译器黑客,如果可能的话,我也想将某个应用程序的运行时依赖项限制为 ruby 标准库

答:

0赞 Casper 11/6/2021 #1

Ruby 不会以任何方式导出FD_SETSIZE,因此检查大小的唯一方法是使用编译器。

与其构建自己的扩展,最省事的方法可能是使用 RubyInline,这使得检查变得非常简单:

gem install RubyInline

然后:

require 'inline'

class FdTest
  inline do |builder|
    builder.c "
      long fd_setsize(void) {
        return FD_SETSIZE;
      }"
  end
end

puts FdTest.new.fd_setsize

=> 1024

这甚至可以半移植到 Windows,前提是您在 WSL、Cygwin、MinGW 或类似的东西下运行。甚至可以在 Visual Studio 下工作,前提是它安装了 C 支持。

将其构建为扩展可能是确保更好兼容性的另一种解决方案,然后您可以为所需平台提供预编译的二进制文件。

这完全取决于您愿意经历多少麻烦才能在所有可能的平台上提取这些信息,因为实际上不存在完全独立于平台的解决方案。