polling file descriptor

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
Hello,

for the embedded MIPS-based platform I'm implementing a small program to
poll GPIO, i.e. I'm using chip vendor's user level GPIO library with basic
functionality (open /dev/gpio, read, write pin etc.). The design is
straightforward:

int gpio_fd;
fd_set rfds;

gpio_fd = gpio_open(...);

while (1) {
    FD_ZERO(&rfds);
    FD_SET(gpio_fd, &rfds);

    if (select(gpio_fd + 1, &rfds, NULL, NULL, NULL) > 0) {
        if (FD_ISSET(gpio_fd, &rfds)) {
            /* read pins and similar */
        }
    }
}

But I'm facing a secrious problem - this application when ran with '&' at
the end, i.e. put it in background, consumes 99% CPU, this is obviously
because of tight loop, but I observed the similar approach in many
networking code and it worked fine.

Am I missing something, can it be a defect of the gpio library ?

Actually, just a single "while(1) ;  "  does the same effect. Can it be the
"natural" behavior of the kernel?

Thanks.

--
Mark


Re: polling file descriptor
Quoted text here. Click to load it

It is in the nature of the handle you're polling: A network socket
is not always ready, but a GPIO pin read is. The select() will
yield when the polled handle is not ready. You have to insert
some kind of delay in the loop to drop the CPU load to an
acceptable level.

Quoted text here. Click to load it

It is correct. See above.

--

Tauno Voipio
tauno voipio (at) iki fi

Re: polling file descriptor
Quoted text here. Click to load it

Sorry, not quite understand your idea. Could you please elaborate on that?

Quoted text here. Click to load it


Just now I've checked the gpio driver's source code, and found that it
doesn't seem to implement 'poll' method (the field in 'struct
file_operations' ), may be that could be one of the reasons, i.e. select()
in my program quickly returned and didn't do anything. So,  does it make
sense to try to add this functionality in the driver and see the results ?

--
Mark


Re: polling file descriptor
Quoted text here. Click to load it

The 'handle' is the number of the I/O channel or socket.

A network interface has to wait for an arriving packet or
for space in the send buffer. The driver blocks for this
wait time, yielding control to other threads of execution
in the system. The hardware mechanism for unblocking
the driver is an interrupt connected to the driver and
associated hardware.

There is nothing to wait for in the GPIO driver, so it is
always immediately ready.

Quoted text here. Click to load it



You would have a need for an appropriate interrupt with
a suitable handler. Do you have the hardware documentation
for the GPIO you have?

If you're going to do it, read the book

  Linux Device Drivers

first. It is available as a PDF, google for it.

--

Tauno Voipio
tauno voipio (at) iki fi



Re: polling file descriptor

[...]

Quoted text here. Click to load it

Provided that it is possible block threads calling into the driver
until they are woken up by some external event (such as an interrupt)
signalling that 'something of interest has happened', my opinion would
be that it makes sense technically: Even if no other application can
make use of the CPU time freed in this way, it should still reduce
power consumption and heat dissipation.

Re: polling file descriptor
Quoted text here. Click to load it

You are 'select'ing the gpio fd for readability. Do you have any idea
what this actually means semantically? If not, it is a programming
error to do it.

For example, with a TCP connection, we know that 'readability'
generally means that a read for a normal data would not block. So if
we want to wait until a normal read would not block, we select for
readability.

That is, our decision to call 'select' is based on the semantics of
the a 'select' hit being what it is we want to wait for. Unless you
know that the semantics of a 'select' hit being something you want to
wait for, it is an error to call 'select'.

I suspect that you don't know that, and so your calling 'select' is an
error.

DS

Re: polling file descriptor
Quoted text here. Click to load it

Could you please be more concrete?

As Tauno has already pointed out, select()'ing gpio file descriptor doesn't
make much sense as it's always ready, unlike socket which may not be ready
and thus application select()ing it would sleep.

--
Mark


Re: polling file descriptor
Quoted text here. Click to load it

This depends on the driver and the configuration of the gpio.

Re: polling file descriptor
Quoted text here. Click to load it

As for the gpio driver I have, it operates on-chip registers (GPIO mask,
enable/disable etc.), and exposes 'ioctl' to user space. So for this
particular driver it seems there is no need for pollling.

Could you give some example when select() will be needed?

--
Mark


Re: polling file descriptor
Quoted text here. Click to load it

Polling is the opposite of using select(), and seems to be exactly what
you want. Polling means checking some status from time to time instead
of waiting for it to change.

Quoted text here. Click to load it

Perhaps a more detailed explanation of select() is in order.

What the system call select() does, is to take a set of file descriptors
and wait until reading (or writing) can be done on one of the
descriptors without blocking the process. Separate sets are provided to
select() to wait for reading, writing, and exception conditions.

The most common use of the system call is in the situation where you
have several file descriptors which provide incoming data att different
rates, and you need to read each descriptor repeatedly to handle the
data as it comes in. An example of this is a program that has many
network connections open at the same time, and is receiving data from
various sources more or less intermittently.

In that situation, if you simply make a read() call on one of the
descriptors, the process will block indefinitely, until data arrives on
that particular descriptor. This could take forever, and the process
will be stuck in read() in the meantime. During that time, data may well
arive on the other descriptors, but the program will not do anything
about it since it is busy waiting for data on the first descriptor.

What you do instead, is you stick all the descriptors in a set, and call
select(), giving that set as the "read set", to wait for reading
becoming possible without blocking. Select() then blocks the process
until data arrives on *any one* of the descriptors, at which time it
returns to the process, indicating on which descriptor data arrived.

This way, you can have multiple sources of data and service them all in
a timely manner. The other way to do that would be to poll all of the
sources - that is, to loop and check each descriptor in turn to see if
any data has arrived yet, repeating until no more data is to be read
from any descriptor. The downside to this is that either you loop in a
tight loop, using all the CPU time available, or you put a delay in
between the checks, checking the descriptors at regular intervals, say
once a second. This decreases CPU waste, but produces latencies in the
reception of the data, since data could be available on one of the
descriptors for a whole second before your process checks for it.

Does this make the use of select() clear?


Bjarni
--

                        INFORMATION WANTS TO BE FREE

Re: polling file descriptor
Quoted text here. Click to load it

I understand the difference, I was referring to 'polling' in the linux
driver context (field 'poll' in the 'struct
file_operations'  ).

Quoted text here. Click to load it
Thank you very much for your explanation, but how dos it prove that select()
for this particular case (gpio) isn't needed ?

--
Mark


Re: polling file descriptor
Quoted text here. Click to load it

Depends on how you define the semantics of select(). I would expect a
basic gpio driver to return the state of the pins on read, and since
'current state' is always available there is no need for something like
select() - it is a null op.

Having said that, when writing control software that has to deal with
digital I/O pins I almost always end up with a process or thread that
polls the I/O pins, and communicates status /changes/ to the rest of the
app through some IPC mechanism. If the driver supported a select with
semantics defined as 'only return if there was a state change since the
last read on this file descriptor' it would make life much easier for
the application programmer.


-j

Re: polling file descriptor
Quoted text here. Click to load it

This agrees with the very first explanation in this thread, and I understand
it, but other posters seems to have disagreed and totally misled and
obfuscated me.

--
Mark


Re: polling file descriptor
Quoted text here. Click to load it

No, other posters were offering alternatives to the rather simplistic
implementation of a GPIO driver you seem to have.   If the GPIO hardware
(PCI?) can raise INTA, INTB, INTC or INTD when a GPIO pin changes state,
then the select/poll implementation for that driver can respond when the
pin changes state - then you don't need to periodically test the state of
the pin in your application.

scott

Re: polling file descriptor
Quoted text here. Click to load it

That does not seem like a nice device driver design, IMHO a decent
driver should react to a state change with select().

-Michael

Re: polling file descriptor
Quoted text here. Click to load it

I'm not sure whether you mean the call to select in your code or the
implementation of select in the driver.

For the call in your code: By the fact that your program uses 99% CPU.
The select call is obviously not waiting for anything to change.

For the implementation of select functionality in the driver: Well,
you're the one who knows what sort of response times and efficiency your
application requires. If you need to respond quickly to events on the
GPIO, and the GPIO hardware provides interrupts, then by all means add
select support to the driver. If periodic polling will do, then just
doing that would be easiest, and doesn't require any hardware support.

For each source of data, it is up to you to decide which of the two
models to employ:

   1. The source can never be hung waiting for data to become
      available, and you have to decide how often you need to
      check it to determine the current state, handling multiplexing
      of multiple sources and frequency of polling by yourself.

   2. The source only occasionally has data available for reading,
      and in between, any attempt to read will block for some
      possibly variable amount of time. In this case, if your
      program needs to wait for data to become avilable before
      proceeding, use select on all the sources you need to
      receive data from (or just read if there is only one source).

If your program needs both to poll some sources periodically and handle
arriving data on blocking file descriptors in a timely manner, use the
timeout parameter to select, in which case select will provide you with
the time base for the polling.

Does this answer your question, or am I barking up the wrong tree?


Bjarni
--

                        INFORMATION WANTS TO BE FREE

Re: polling file descriptor
Quoted text here. Click to load it
So it turnes out that 'select' on a gpio does make sense, unlike what was
claimed on this thread before ?

For the purpose of my application, accuracy and quick response isn't
necessary, so I ended up with a simple 'while'-style polling and a usleep,
so it doesn't consume 99% of the CPU. This is sufficient.

--
Mark


Re: polling file descriptor

Quoted text here. Click to load it

True !

Unfortunately the more modern version of "select()" is called "epoll()"
and of course does not do any polling.

No idea who invented this name :(.

-Michael

Re: polling file descriptor
Quoted text here. Click to load it

I could construct a contrived example where select could be used on a
file descriptor referring to a chardev (assumption) whose device
driver provides access to GPIOs: In this case, events of interest
wouldn't be GPIO states but GPIO state transitions and a read
operation which blocks until the next GPIO state change has occurred,
with this change being signalled by an interrupt. But I don't quite
understand why this would be useful (the construction of the contrived
example).

Generally 'select' (and similar routines) are only useful together
with file descriptors referring to 'things' (devices, files, network
connections etc) which provide read and write operation that might
need to block.

Re: polling file descriptor
Quoted text here. Click to load it


Since you've noticed that select() on gpio file descriptor depends on the
driver and the configuration of the gpio, I reasonably assumed that there
should be an appropriate case of gpio driver, where select()ing would make
perfect sense.

--
Mark


Site Timeline