I/O Multiplexing The role of the ‘poll()’ method in Linux device-driver operations

advertisement
I/O Multiplexing
The role of the ‘poll()’ method in
Linux device-driver operations
struct file_operations fops;
•
•
•
•
•
•
•
read:
write:
open:
close:
llseek:
…
poll:
//  what is this function for?
Recall ‘watchtsc.cpp’ demo
• After some initializations, this application
entered an endless loop, rereading from
the ‘/dev/tsc’ device special file.
• But it also checked for user input from the
keyboard, so a user could break out of the
endless loop in order to quit the program.
Illustrates I/O Multiplexing
Read from /dev/tsc
redraw
display
Read from keyboard
maybe quit
More than just one source for input
Remember ‘read()’ semantics
• If device-driver’s ‘read()’ function is called
before the device has any data available,
then the calling task is expected to ‘sleep’
on a wait-queue until the device has at
least one byte of data ready to return.
• The keyboard’s device-driver behaves in
exactly that expected way: it ‘blocks’ if we
try to read when there are no keystrokes.
Blocking versus Multiplexing
• If we want to read from multiple devices,
we are not able to do it properly with the
read() system-call
• If one device has no data, our task will be
blocked, and so can’t read data that may
become available from some other device
Idea: use ‘nonblocking’ i/o
• When we ‘open()’ a device-file, we could
specify the ‘O_NONBLOCK’ i/o mode
• For the keyboard: two problems with this:
– The ‘stdin’ device is already open by default
– If a task tries to do multiplexing with devices
that have been opened in non-blocking mode,
it will likely consume way too much cpu time!
Better idea: use ‘select()’
• The ‘select()’ system-call was designed to allow
applications to efficiently perform i/o multiplexing
• With ‘select()’ the application informs the kernel
as to which system devices it is interested in
• The kernel then ‘polls’ those devices, to see if
any of them is ready to do i/o without blocking
• If not, it puts the process to sleep until at least
one device is ready to do i/o without blocking
Calling ‘select()’
•
•
•
•
Application needs an ‘fd_set’ structure
For reading, for writing, and for errors
And maybe also a ‘timeout’ structure
In our ‘watchtsc.cpp’ demo:
– We only were interested in reading
– Not interested in writing or in errors
– And not concerned about ‘timeouts’
• Full details on the ‘man’ page for ‘select()’
Driver needs ‘poll()’ method
• To support the ‘select()’ system-call, our
‘tsc.c’ driver needs to implement ‘poll()’
• Our textbook tells what we need to do
• Just two things:
– Need to call the kernel ‘poll_wait()’ function
– Return a bitmap indicating device readiness
prototype for ‘poll()’ method
#include <linux/poll.h>
// for ‘poll_table’
static int ready;
// kernel-timer’s flag
DECLARE_WAIT_QUEUE_HEAD( wq );
static unsigned long
my_poll( struct file *file, poll_table *wait );
Actions in our ‘poll()’ function
static unsigned long
my_poll( sruct file *file, poll_table *wait )
{
unsigned long mask = 0;
poll_wait( file, &wq, wait );
if ( ready )
// our kernel-timer’s flag
mask |= ( POLLIN | POLLRDNORM );
return
mask;
}
An experiment with ‘poll()’
•
•
•
•
•
•
•
Modify the ‘tsc.c’ device-driver code
Include ‘poll()’ in ‘file_operations’ struct
Use a kernel software timer in ‘read()’
Use 5-second delay between ‘reads’
Run ‘watchtsc’ with polling implemented
And run ‘watchtsc’ with polling ommitted
Note responsiveness to keyboard input!
Does ‘ram.c’ need ‘poll()’?
•
•
•
•
•
•
•
The system memory is ‘volatile’
Contents of memory continually changing
For example, the ‘jiffies’ variable
And lots of other examples as well
Our ‘fileview.cpp’ tool doesn’t show this
It ‘blocks’ until the user presses a key
Would be much better to use ‘select()’
Download