Hardware Reference
In-Depth Information
Each segment to be transmitted is described by one iov[x] member, each consisting
of a buffer pointer and the number of bytes. The writev(2) system call is told how many
iov[] entries to use in its third calling argument.
Error EINTR
One error code that afflicts many device I/O system calls is the EINTR error, “Interrupted
system call.” This error code applies to read(2) , readv(2) , write(2) , and writev(2) on
devices that may “block” execution until the required data has been fully read/written.
(This also applies to ioctl(2) when I2C I/O is performed.) The EINTR error is not
returned for I/O to disk because these I/O calls don't block for a long time (the I/O is to/
from a file system disk memory buffer). The application developer should otherwise plan
on handling this error.
The EINTR error is the Unix way of working with signals. Consider what happens
when your application is waiting for a single keystroke from the user at a terminal (or
reading a packet from an AVR class device):
rc = read(fd,buf,n); /* Block until n bytes read */
Until that read is satisfied (or the file descriptor is closed), execution will stop there.
In the meantime, another process or thread may signal your application to do something,
perhaps to shut down and exit. A signal handler like the following is invoked when the
signal is handled:
static void
sigint_handler(int signo) {
is_signaled = 1; /* Please exit this program */
}
At this point, your application is in the middle of a system call, waiting to read
from the serial port. The system call's registers are saved on the stack frame, and your
application has entered into the kernel. The handling of the signal means that the kernel
calls your signal handler, placing another stack frame on your current stack.
Because a signal can arrive at any time, there are many things you can't do from within
a signal handler. For example, you must not invoke malloc(3) or other non-reentrant
functions. Otherwise, you risk doing another malloc(3) inside an interrupted malloc(3) ,
which leads to disaster. The important point here is that a very limited number of safe
things can be performed from inside a signal handler.
One thing that is safe to do in a signal handler is to set a global variable of some kind,
like the is_signaled variable in the example. One problem remains: how does the code
blocked in the read(2) call respond to this notification? When the signal handler returns,
the application will continue to block trying to read from the serial port.
 
Search WWH ::




Custom Search