开发者

How C++ select() function works in Unix OSs?

I have used the select() function to implement servers, but now I have to implement it by myself (as a part of a project).

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

Can anyone please help me to implement this function? Any sources, artic开发者_JAVA技巧les? Can anyone explain what is happening in that function?


select is an operating system primitive. It cannot be implemented using other portable constructs, such as pthreads.

You can think of it as a differently-specialized version of pthread_cond_wait, which receives a signal associated with a condition variable. pthread_cond_wait stalls the current thread until the signal is received, then (optionally) verifies that the signal was associated with the appropriate mutex, then acquires the mutex, and continues along. select receives a signal, confirms (or at least guarantees) its receipt, and passes the information along. It also deals with signals that were received before it was called.

So, pthread_cond_wait is not really primitive in terms of implementation; it's designed to be very safe semantically. That is the spirit of pthreads, for better or worse. Atomic variables, available in various libraries, provide an unsafe primitive-implementation alternative to pthreads for synchronization jobs, but signaling involves scheduling and unscheduling threads, which is pretty platform specific. (Well, on second thought, I guess you could implement select with spinlocks. I shudder at the thought.)

It's a great exercise to try, though.


You can always look at open source implementations for inspiration and/or theory of operation.

I believe the basic premise is that the process calling select() is put on "wait lists" connected to each of the sockets in the request, and then the kernel can check whenever it goes to update the status of a socket which processe(s) are on that socket's lists, and make them runnable.

This is of course a very high-level description though that just glosses over many of the myriad details you'll need to cover to get this right.


If you're implementing select, then presumably you (or your colleagues) are implementing a significant part of the OS interface. So, it depends how you're implementing the I/O subsystem, and the scheduler.

If you're not implementing the scheduler, then you need some kind of "control centre" which uses synchronisation primitives (probably condition variables) to track changes in the states of the file descriptors you're interested in.

After initially checking the current state of the file descriptors listed, fundamentally, how select works is that it doesn't return until the timeout expires, or one of the descriptors it cares about changes state (in a way that it cares about). This could be handled entirely in the scheduler, so that the thread is unavailable for scheduling until the required conditions occur, or the thread could block until some change occurs that it might be interested in, check whether it really is interested, and then either return if it is, or block again if it isn't. At the extreme of this approach, a completely dumb (and inefficient) implementation could have a single condition variable that every caller to select waits on, and which is broadcast by the I/O system every time a state change occurs (as Potatoswatter points out, you also have to record the state).

If you're not implementing the I/O subsystem, then the only way to implement select is on top of some other, similar primitive which your I/O subsystem does support. Alternatively, take on the task of implementing I/O: wrap everything in your own layer, and make select available only through that layer. The implementation of this layer depends on the underlying API, but if all else fails you can create one thread per file descriptor, do blocking I/O ops in that thread, and then notify your "control centre" when the fd is readable, writable, or has errors.

Get the design right first, which probably means studying how other OSes do it. Otherwise you will spend the next 2 years fixing race conditions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜