Josh Brittain
Josh Brittain

Reputation: 2212

Are file descriptors for linux sockets always in increasing order

I have a socket server in C/linux. Each time I create a new socket it is assigned a file descriptor. I want to use these FD's as uniqueID's for each client. If they are guaranteed to always be assigned in increasing order (which is the case for the Ubuntu that I am running) then I could just use them as array indices.

So the question: Are the file descriptors that are assigned from linux sockets guaranteed to always be in increasing order?

Upvotes: 5

Views: 5717

Answers (3)

Jay Medina
Jay Medina

Reputation: 574

Let's look at how this works internally (I'm using kernel 4.1.20). The way file descriptors are allocated in Linux is with __alloc_fd. When you do a open syscall, do_sys_open is called. This routine gets a free file descriptor from 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 calls __alloc_fd setting minimum and maximum fd:

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

__alloc_fd gets the file descriptor table for the process, and gets the fd as next_fd, which is actually set from the previous time it ran:

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;

So you can see how file descriptors indeed grow monotonically... up to certain point. When the fd reaches the maximum, __alloc_fd will try to find the smallest unused file descriptor:

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

At this point the file descriptors will not be growing monotonically anymore, but instead will jump trying to find free file descriptors. After this, if the table gets full, it will be expanded:

error = expand_files(files, fd);

At which point they will grow again monotonically.

Hope this helps

Upvotes: 12

richvdh
richvdh

Reputation: 1253

FD's are guaranteed to be unique, for the lifetime of the socket. So yes, in theory, you could probably use the FD as an index into an array of clients. However, I'd caution against this for at least a couple of reasons:

  • As has already been said, there is no guarantee that FDs will be allocated monotonically. accept() would be within its rights to return a highly-numbered FD, which would then make your array inefficient. So short answer to your question: no, they are not guaranteed to be monotonic.

  • Your server is likely to end up with lots of other open FDs - stdin, stdout and stderr to name but three - so again, your array is wasting space.

I'd recommend some other way of mapping from FDs to clients. Indeed, unless you're going to be dealing with thousands of clients, searching through a list of clients should be fine - it's not really an operation that you should need to do a huge amount.

Upvotes: 4

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798746

Do not depend on the monotonicity of file descriptors. Always refer to the remote system via a address:port pair.

Upvotes: 2

Related Questions