I want to read from serial port with timeout but readcond function don’t satisfy me because the timeout is specified only in 1/10 of a second. It’s not enaugh for me. So I was going to use read function which can be interrupted by a signal before it reads any data and a timer to send the signal when the timer expires.
It could look like this:
When I had to handle data/signals over serial ports (up to 48 per node) with very high time precision, I did it as follows:
All ports are handled not by Dev.ser, but by specially written timer interrupt handler (TIH)
TIH initializes all ports on the start and attaches the timer interrupt (0). From within the interrupt it monitors ports and if data is ready (DR on LSR) puts it into a buffer in the shared memory and then, from outside the interrupt, it kicks the application with SIGALRM.
The application normally sleeps in pause (), until it is kicked by SIGALRM. Then it gets a byte from a buffer.
These are just tiny extracts. I had to remove lots of code, so many definititions are lost and examples will not compile. And I had to remove all the comments as misleading and confusing.
To compile interrupt handler, you need to use additional options with cc:
I need 1/100 of a second resolution. It seems select function will be useful.
However I am still curious to know how to interrupt read function using signals?
In documentation they say that “If read() is interrupted by a signal before it reads any data, it returns a value of -1 and sets errno to EINTR. However, if read() is interrupted by a signal after it has successfully read some data, it returns the number of bytes read.”
Does select() generate that signal? Or can I generate one of POSIX’s signals to interrupt read()?
With select you don’t need the signals. select will unblock when there is data on the serial port or if the timeout expired. Hence if select unblock because of data on the serial port, you just need to issue a read to obtain the data (and read in non block mode) and empty the buffer.
Now if you expect a LOT of data on these serial port and a constant flow of them, it might not be such a bad choise to poll all the serial port with a non blocking read().
If you’re using QNX6 you could always preceed your call to read() with a call to TimerTimeout(…,_NTO_TIMEOUT_REPLY,…) as well. If the read times out, it will return with ETIMEDOUT (or possibly EINTR…can’t remember). If you do go this route, make sure there are NO calls between the TimerTimeout() call and the read() call.
read() is a library call, not a kernel call. Only kernel calls are subject to timeout using TimerTimeout.
There maybe several kernel calls inside of read(), the rule you quote here “make sure there are NO calls between the TimerTimeout() and the read()” cannot be followed, since the caller has no idea how many kernel calls read() is making nor in what order.
There is no guarantee of this. Anyone who designs their code based on the underlying implementation of a API deserves what they get when they upgrade the O/S and their code stops working.