Using pipes in bash to buffer data from a serial device

bash, serial-port

Solution

The problem isn't the pipe. It's the serial device.

When you write

while true; do
  read -t10 -d$'\n' input_from_serial_device </dev/ttyS0
  # use a lot of time
done

the consequence is that the serial device is opened, a line is read from it, and it is then closed. Then it is not opened again until `# use a lot of time` is done. While a serial device is not open, incoming serial input is thrown away.

If the input is truly coming in faster than it can be processed, then buffering isn't enough. You'll have to throw input away. If, on the other hand, it's dribbling in at an average speed which allows for processing, then you should be able to achieve what you want by keeping the serial device open:

while true; do
  read -t10 -r input_from_serial_device
  # process input_from_serial_device
done < /dev/ttyS0

Note: I added `-r` -- almost certainly necessary -- to your `read` call, and removed `-d$'\n'`, because that is the default.

Problem

I have a script that looks something like: ``` while true; do read -t10 -d$'\n' input_from_serial_device </dev/ttyS0 # do some costly processing on the string done ``` The problem is that it will miss the next input from the serial device because it is burning CPU cycles doing the costly string processing. I thought I could fix this by using a pipe, on the principle that bash will buffer the input between the two processes: ``` ( while true; do read -d$'\n' input_from_serial_device </dev/ttyS0 echo $input_from_serial_device done ) | ( while true; do read -t10 input_from_first_process # costly string processing done ) ``` I firstly want to check that I've understood the pipes correctly and that this will indeed buffer the input between the two processes as I intended. Is this idea correct? Secondly, if I get the input I'm looking for in the second process, is there a way to immediately kill both processes, rather than exiting from the second and waiting for the next input before exiting the first? Finally, I realise bash isn't the best way to do this and I'm currently working on a C program, but I'd quite like to get this working as an intermediate solution. Thank you!

Original source