我在C / linux中有一个套接字服务器。每次我创建一个新套接字时,都会为其分配一个文件描述符。我想将这些FD用作每个客户端的唯一ID。如果保证它们总是按递增顺序分配(我正在运行的Ubuntu是这种情况)那么我可以将它们用作数组索引。
所以问题是:从linux套接字分配的文件描述符是否始终保持递增顺序?
答案 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将单调分配。 accept()将有权返回一个编号很高的FD,这会使你的数组效率低下。如此简短的回答你的问题:不,他们不能保证是单调的。
您的服务器可能最终会出现许多其他开放的FD - stdin,stdout和stderr,但只有三个 - 所以你的阵列再次浪费空间。
我建议从FD到客户端的其他映射方式。实际上,除非您要与成千上万的客户打交道,否则通过客户列表进行搜索应该没问题 - 这不是一个您需要做大量工作的实际操作。
答案 2 :(得分:2)
不要依赖文件描述符的单调性。始终通过地址:端口对参考远程系统。