[comp.unix.programmer] Serial Polling - Opinions?

markt@tse.uucp (Mark Turner) (06/25/91)

Hi folks. Can anyone out there suggest alternatives to the following 
implementation of a RS-232 serial polling program (explained below)? I'm
mainly interested in the types of solutions that others have found for this
problem. I've listed several areas of concern following the explanation.

Currently, I'm working on a small program that reads a data feed from an 
RS-232 serial port. The application consists of several processes, the first of
which reads data from the port and throws the raw data into a circular buffer 
stored in shared memory (I'll call this the READER process). A second process 
reads the data from the buffer (the PROCESSOR process) and constructs messages 
to send to a SERVER process that is responsible for broadcasting to the 
appropriate clients.

Notes: 

(1) The circular buffer *may* fill, in which case the READER executes the time()
    system call in the hope that the PROCESSOR will be scheduled and free up 
    some room in the buffer. This type of contention has not been a problem 
    to date. 

(2) The PROCESSOR is a simple implementation. It simply uses the open() and 
    read() calls to get at the ASCII transmission.

(3) The priority of these processes have been bumped up so that the READER 
    process has the highest priority of any user processes; hopefully, this will
    prevent data loss when the system is heavily loaded.

Areas of Concern:

(1) This configuration does not guarantee that data won't be lost on the
    incoming line. Yech! Should I be thinking about something like SLIP or
    PPP? (I really don't know much about these protocols.) Should I build much
    of the READER/PROCESSOR functionality into a custom device driver?

(2) Is there any real advantage in splitting the processing between the
    READER and the PROCESSOR? Perhaps they should reside in the same program,
    where the program itself arbitrates between the two operations.

(3) The main design considerations are performance and accuracy. (Is that all?!)

If you've dealt with similar problem, or have a suggestion, I'd appreciate the
help. I'm hoping to avoid some of the common glitches that others have already
dealt with in the past. 

--------------------------------------------------------------------------------
Regards, Mark Turner (markt@tse.UUCP)

les@chinet.chi.il.us (Leslie Mikesell) (06/28/91)

In article <1991Jun25.140918.22908@tse.uucp> markt@tse.UUCP (Mark Turner) writes:
>Currently, I'm working on a small program that reads a data feed from an 
>RS-232 serial port. The application consists of several processes, the first of
>which reads data from the port and throws the raw data into a circular buffer 
>stored in shared memory (I'll call this the READER process). A second process 
>reads the data from the buffer (the PROCESSOR process) and constructs messages 
>to send to a SERVER process that is responsible for broadcasting to the 
>appropriate clients.

I've done something similar using a FIFO.  The serial port reader just
writes the data to the FIFO, the processor can either do blocking or
non-blocking reads, depending on whether it needs to do anything when
no data is available.

>(1) The circular buffer *may* fill, in which case the READER executes the time()
>    system call in the hope that the PROCESSOR will be scheduled and free up 
>    some room in the buffer. This type of contention has not been a problem 
>    to date. 

With a FIFO, you are limited to the machine's pipe buffer size (generally
5 or 10K)  but that has worked well for my purposes.  The process writing
to the FIFO can tell if an overrun happens or block until space is available
but the reading side can't.
 
>(2) The PROCESSOR is a simple implementation. It simply uses the open() and 
>    read() calls to get at the ASCII transmission.

Do you mean the READER here?  You probably want to put the serial line in
raw mode and attempt to read fairly large chunks.

>(1) This configuration does not guarantee that data won't be lost on the
>    incoming line. Yech! Should I be thinking about something like SLIP or
>    PPP? (I really don't know much about these protocols.) Should I build much
>    of the READER/PROCESSOR functionality into a custom device driver?

This depends on what you have on the sending side.  In my case it is coming
from a satellite broadcast and there is no way to interact other than possibly
adding a serial buffer box that would respond to flow control.  Fortunately
it hasn't been a problem.

>(2) Is there any real advantage in splitting the processing between the
>    READER and the PROCESSOR? Perhaps they should reside in the same program,
>    where the program itself arbitrates between the two operations.

Splitting them worked well for me - connecting through a FIFO allows me
to stop and start the processing program (with different parameters or
a replacement program) without losing any inbound data.   I actually have
four processes linked through 3 FIFO's plus another FIFO to accept
semi-interactive commands.  My second process does nothing but handle the
input from it's serial port data, so it does blocking reads and writes its
processed output to another FIFO.  The third process multiplexes this data
with that from another serial port reader and lots of other stuff so it
does non-blocking reads on its input FIFOs. A 1 second sleep() in the
loop when all of the FIFOs are empty is acceptable for this application and
keeps the syscalls/sec down.

>(3) The main design considerations are performance and accuracy. (Is that all?!)

The biggest concern is the number of system calls per second you are making
and whether you are busy-looping anywhere.  How are you interlocking the
shared memory access between the reader and processor?  Using FIFOs I
write usable-size chunks to make data available as soon as possible, but
the reading side requests a large buffer on each read() and parses the
boundaries itself.  Also, if any of the data from the serial port is
unnecessary, the reading process could discard it instead of passing it
on.  If you have a choice, make sure that your serial ports have hardware
buffering and that you are using the most efficient modes for it.

Les Mikesell
  les@chinet.chi.il.us