Linux套接字的文件描述符总是按递增顺序排列

时间:2012-02-21 10:47:19

标签: linux sockets file-descriptor

我在C / linux中有一个套接字服务器。每次我创建一个新套接字时,都会为其分配一个文件描述符。我想将这些FD用作每个客户端的唯一ID。如果保证它们总是按递增顺序分配(我正在运行的Ubuntu是这种情况)那么我可以将它们用作数组索引。

所以问题是:从linux套接字分配的文件描述符是否始终保持递增顺序?

3 个答案:

答案 0 :(得分:5)

让我们看看它是如何在内部工作的(我使用内核4.1.20)。在Linux中分配文件描述符的方式是使用__alloc_fd。当您执行打开的系统调用时,将调用do_sys_open。此例程从get_unused_fd_flags:

获取一个空闲文件描述符
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{ 
    ...
    fd = get_unused_fd_flags(flags);
    if (fd >= 0) {
        struct file *f = do_filp_open(dfd, tmp, &op);

get_unused_d_flags调用__alloc_fd设置最小和最大fd:

int get_unused_fd_flags(unsigned flags)
{
    return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags);
}

__ alloc_fd获取进程的文件描述符表,并将fd作为next_fd获取,该实际上是从上次运行时设置的:

int __alloc_fd(struct files_struct *files,
           unsigned start, unsigned end, unsigned flags)
{
    ...
    fd = files->next_fd;
    ...
    if (start <= files->next_fd)
        files->next_fd = fd + 1;

所以你可以看到文件描述符的确是单调增长的......直到某一点。当fd达到最大值时,__ alloc_fd将尝试查找最小的未使用文件描述符:

if (fd < fdt->max_fds)
    fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, fd);

此时文件描述符将不再单调增长,而是跳转尝试查找空闲文件描述符。在此之后,如果表格已满,它将被展开:

error = expand_files(files, fd);

此时他们会再次单调地成长。

希望这有帮助

答案 1 :(得分:3)

在套接字的生命周期内,FD保证是唯一的。所以是的,理论上,你可以使用FD作为客户端数组的索引。但是,至少有几个原因我要小心这一点:

  • 正如已经说过的那样,没有保证,FD将单调分配。 accept()将有权返回一个编号很高的FD,这会使你的数组​​效率低下。如此简短的回答你的问题:不,他们不能保证是单调的。

  • 您的服务器可能最终会出现许多其他开放的FD - stdin,stdout和stderr,但只有三个 - 所以你的阵列再次浪费空间。

我建议从FD到客户端的其他映射方式。实际上,除非您要与成千上万的客户打交道,否则通过客户列表进行搜索应该没问题 - 这不是一个您需要做大量工作的实际操作。

答案 2 :(得分:2)

不要依赖文件描述符的单调性。始终通过地址:端口对参考远程系统。