[En-Nut-Discussion] Let's start another discussion: Wait on multiple events

duane ellis ethernut at duaneellis.com
Wed Feb 27 12:14:04 CET 2008


Ole Reinhardt wrote:
> Does anyone know more about the internal implementation of select and
> poll? Is there a possibility to "emulate" select with the existing NutOs
> event queues?
>   
I am familiar with it, and wrote a variant or two before on other systems.
but not that familiar _yet_ with the internals of nut.

if you want to learn more about how select()/poll() work in linux, it is
easier to look at it from a device driver point of view.

There is an old joke, it goes like this:
      Rule #1 - The wife is always correct.
      Rule #2 - If the wife is every wrong, refer to rule #1.

In UNIX, the rule is like this:
     Rule #1 - You are a file descriptor, you are never anything else.
     Rule #2 - If you are not a file descriptor, You are wrong. See Rule #1.

What matters is the system must have a means to 'unify' all file
descriptors into a simple integer.
For all things, everywhere - see the Rule #1 joke. That totally
simplifies any select()/poll() implementation.
One must be able to map an arbitrary FD into the "poll" function for an
arbitrary thing. See below.

>> Any suggestions or literature on this subject?

The "Linux Device Drivers" book - is a very good good.

I assume you understand a user_land file descriptor is mapped to a
kernel side "kernel_filepointer".
And the file pointer has a "file operations" pointer - which - points at
a set of function pointers.
one of which is the "poll()" function.

======
select() is simple and is as follows:

LOOP:
   for each bit in the 3 arrays
      If one is set - translate corresponding user FD into a kernel FP.
      Call that FD->FOPS->POLL() function, it returns a bit mask.
      Based on that bit mask - clear the bit in the array.
   Next Bit.

    If any result array contains a set bit
         Count how many bits are set.
         Update "timeout"
         Return the count of bits still set.
    else
         If no time remains
                 zero all result bits, update timeout,
                 return 0.
         else
             setup up timeout.
             Sleep the current task.
             Goto LOOP.
         endif
    endif
EndSelect
======

The trick is - that *ALL* open files in linux look the same.
Everything is a "file descriptor" - everything has a "file_ops" structure.
Thus, everything has a 'poll()' function, Ta-Da... Solved.
See Rule #1 - and Rule #2.

The confusing/hidden part is the sleep scheme.
In the device driver, you effectively "wake" the task if the thing
becomes readable.
Or becomes writable - as the case may be.  Linux has several efficient
ways of doing it.
One can always be less efficient - ie: Wake up select() - which will
re-poll everything.

======

The other trick is to return '-ERESTART' - which tells the task sorry
you must try again.
A helpful 'not-really-an-error' trick that solves many problems.

======

-Duane.






More information about the En-Nut-Discussion mailing list