增加FD_SETSIZE的限制并选择

Viv*_*oel 17 c linux file-descriptor

我想为我的系统增加FD_SETSIZE宏值.有没有办法增加FD_SETSIZE所以选择不会失败

R..*_*R.. 14

按照标准,没有办法增加FD_SETSIZE.一些程序和库(libevent脑海中浮现)尝试通过为fd_set对象分配额外的空间并传递大于宏的值FD_SETSIZE来解决这个问题FD_*,但这是一个非常糟糕的主意,因为健壮的实现可能会对参数执行边界检查,如果它超出范围则中止.

我有一个应该始终有效的替代解决方案(即使标准不要求它).而不是单个fd_set对象,分配一个足够大的数组来保存您需要的最大fd,然后使用FD_SET(fd%FD_SETSIZE, &fds_array[fd/FD_SETSIZE])等来访问该集合.

  • @dns:那是假文件.:-)请阅读http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html.好吧,开个玩笑,请解释一下你认为对我的答案"假"的看法. (6认同)
  • 那也不标准.这是一个特定于实现的黑客攻击.我同意在许多实现中,您可以针对此形式进行特定于实现的黑客攻击,但根据标准,它并不正确. (6认同)
  • @AndrewHacking:人们什么时候会厌倦对此发表错误评论?是的,一些实现允许它.不,它根据接口规范无效.相关文字是...... (4认同)
  • 这是错误的答案.请阅读http://support.microsoft.com/kb/111855 (3认同)
  • 根据微软本身"按照标准,没有办法增加FD_SETSIZE"是错误的,因为我从微软自己一字不差地引用:"这个值用于构造select()中使用的fd_set结构.默认情况下WINSOCK.H中的值为64.如果应用程序设计为能够使用超过64个套接字,请在包含WINSOCK.H之前在每个源文件中定义清单FD_SETSIZE." 请阅读http://support.microsoft.com/kb/111855 (2认同)
  • 好吧那么为了适应"标准"你也可以通过简单地改变#define __FD_SETSIZE 1024以下2个文件/usr/include/bits/typesizes.h/usr/include/linux来增加它在Linux/unix/mac varients上的效果/posix_types.h,但是你说你不能增加它,你可以这么回答是错误的 (2认同)
  • 如果我记得op没有;问他们要求如何更改它的标准,所以你的答案会误导告诉别人你不能改变,这就是为什么原来的评论说答案是错误的.你可以改变它你说你无法改变它 (2认同)
  • ...[XSH 2.2.2 命名空间](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02)“应用程序不得声明或定义与标识符同名的标识符保留在相同的上下文中。由于无论何时找到宏名称都会被替换,与范围和名称空间无关,如果包含任何关联的标头,则应用程序不应定义与任何保留的标识符名称匹配的宏名称。 (2认同)
  • @AndrewHacking:我知道的大多数(所有?)系统上的系统调用都会接受任意大小的集合,可能是因为(a)它是与具有不同“FD_SETSIZE”值的不同用户空间实现混合使用的,或者 (b) 它与用户空间实现一起使用,该实现提供了一种请求非默认“FD_SETSIZE”的方法(通过在包含标头之前定义它,或者通过某种其他机制)。另一方面,不能保证在包含“sys/select.h”之前定义“FD_SETSIZE”会起作用;至少在某些系统上,这是一个错误。 (2认同)
  • @AndrewHacking:在这一点上,你正在抓着稻草试图“证明我的答案是错误的”或其他什么,我不太确定为什么。`poll` 变得没有竞争力的规模大约是 50k-100k 文件描述符,当你有这么多时,其他因素可能是你的瓶颈。特别是,dalnet 上的 bahamut-ircd 在 1990 年代的 `poll` 中表现良好,在最高负载的服务器上有 7 万个客户端。因此,从用户空间复制集合“不能很好地扩展”的论点站不住脚。 (2认同)
  • @AndrewHacking:至于我关于“健壮的实现可以检查”的说法,请阅读 glibc 提供的 `bits/select2.h`。只要 `_FORTIFY_SOURCE` 处于活动状态,就会使用它,并且它会根据 *内部常量*(不是您错误地声称可以修改的公共 `FD_SETSIZE`)主动检查 fd 编号并中止程序(有效,因为调用了 UB),如果fd 编号超出范围。 (2认同)
  • @AndrewHacking:从第一个声明开始,你的评论就是错误的。至此我和你的争论结束了。 (2认同)

Bas*_*tch 14

我也建议poll尽可能使用.并且存在一些"事件"处理库,例如libeventlibev(或来自GTK 的Glib的事件能力,或QtCore等),它们可以帮助您.还有像epoll这样的东西.而你的问题与C10k有关


Sim*_*mer 8

用民意调查取代会更好(也更容易).通常poll()是select()的简单替代品,不受1024的FD_SETSIZE限制......

fd_set fd_read;
int id = 42;
FD_ZERO(fd_read);
FD_SET(id, &fd_read);
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(id + 1, &fd_read, NULL, NULL, &tv) != 1) {
   // Error.
}
Run Code Online (Sandbox Code Playgroud)

变为:

struct pollfd pfd_read;
int id = 42;
int timeout = 5000;
pfd_read.fd = id;
pfd_read.events = POLLIN;
if (poll(&pfd_read, 1, timeout) != 1) {
   // Error
}
Run Code Online (Sandbox Code Playgroud)

您需要为pollfd结构包含poll.h.

如果你需要写和读,那么将事件标志设置为POLLIN | POLLOUT.


mpr*_*net 6

为了使用fd_set大于FD_SETSIZE,可以像这样定义扩展的:

#include <sys/select.h>
#include <stdio.h>

#define EXT_FD_SETSIZE 2048
typedef struct
{
    long __fds_bits[EXT_FD_SETSIZE / 8 / sizeof(long)];
} ext_fd_set;

int main()
{
    ext_fd_set fd;
    int s;
    printf("FD_SETSIZE:%d sizeof(fd):%ld\n", EXT_FD_SETSIZE, sizeof(fd));
    FD_ZERO(&fd);
    while ( ((s=dup(0)) != -1) && (s < EXT_FD_SETSIZE) )
    {
        FD_SET(s, &fd);
    }
    printf("select:%d\n", select(EXT_FD_SETSIZE,(fd_set*)&fd, NULL, NULL, NULL));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这打印:

FD_SETSIZE:2048 sizeof(fd):256

选择:2045


为了打开超过1024个文件描述符,需要使用例如增加限制ulimit -n 2048.