Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to associate a file descriptor with user defined data?

Tags:

c

posix

sockets

I am writing a client-server application, and it uses POSIX poll function to provide a form of concurrent client handling. Clients also have state and other related data, which is stored in a client structure.

My immediate problem is that when I get a hint from poll to do I/O on a socket file descriptor that is associated with a client (conceptually), I have to actually match the file descriptor to its associated client data structure. Currently I do a O(n_clients) lookup (my client data structure stores the descriptor), but I was wondering whether there exists a better alternative?

like image 797
amn Avatar asked Nov 17 '11 23:11

amn


People also ask

Can file descriptors be shared between processes?

File descriptors are generally unique to each process, but they can be shared by child processes created with a fork subroutine or copied by the fcntl, dup, and dup2 subroutines.

What are file descriptors and how are they assigned?

File Descriptors are non-negative integers that act as an abstract handle to “Files” or I/O resources (like pipes, sockets, or data streams). These descriptors help us interact with these I/O resources and make working with them very easy. The I/O system is visible to a user process as a stream of bytes (I/O stream).

What data type is a file descriptor?

For most operating systems, a file descriptor (FD) is a small non-negative integer that helps in identifying an open file within a process while using input/output resources like network sockets or pipes. In a way, it can be considered as an index table of open files.


2 Answers

No. If there were, it would have to be tracked by the kernel, and looking up that data would therefore involve a system call. The cost of a system call is an order of magnitude more expensive than doing an O(n) lookup in user space.

How many clients are you dealing with at once? Unless it's on the order of hundreds or more, the cost of a lookup is going to be miniscule compared to the cost of doing any sort of I/O.

Instead of using an O(n) lookup, you could also just use an array indexed by the file descriptor, assuming you won't have more than a certain number of descriptors open at once. For example:

#define MY_MAX_FD 1024  // Tune this to your needs
void *per_fd_data[MY_MAX_FD];

void *get_per_fd_data(int fd)
{
    assert(fd >= 0);
    if(fd < MY_MAX_FD)
        return per_fd_data[fd];
    else
    {
        // Look up fd in a dynamic associative array (left as an exercise to the
        // reader)
    }
}
like image 91
Adam Rosenfield Avatar answered Nov 15 '22 05:11

Adam Rosenfield


Cheapest is to just make a fixed-size array of connection structures, with {state, *context, ..., maybe callback functions} per entry, indexed by fd (=O(1)). Memory is cheap, and you can afford a few hundred or thousand file descriptors and table entries.

EDIT: You dont need to make it fixed size. If your pollstructure or fdset is fixed: make it fixed; otherwise use getdtablesize() or getrlimit() to get the number of entries to allocate.

like image 43
wildplasser Avatar answered Nov 15 '22 07:11

wildplasser