3

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!

5
  • 1
    I don't think you need to run your cooperating processings inside of subshell (I routintely read and write from loops with out the extra ( ) pairs. ) Interesting question, but outside of my range of experience and would be hard to test (who has a serial port any more!? ; -) . Good luck. Commented Jul 22, 2013 at 21:21
  • The pipe will buffer some data, but I don't know how much; it's certainly system dependent. Recent version of Linux, for example, buffer 64K for named pipes, so I assume something similar for ad hoc "unnamed" pipes. Commented Jul 22, 2013 at 21:42
  • 1
    I did some testing on how much I could fit into a pipe with Sun4 (a long time ago) and it boiled down to how much free diskspace in /tmp. (look at where an open session of vi creates it work file, might be /var/tmp on some machines). About the same time, I had a colleague try to stuff a 100MB file into a windows pipe, and I knew from testing on the same project, that windows NT definitely had limits (64K or so). So different OS's and versions (as well as permissioning and configuration) may affect this. The best thing is to set up some tests and see what happens. Good luck. Commented Jul 22, 2013 at 22:43
  • 1
    Whatever PIPE_BUF is for a given system. _POSIX_PIPE_BUF if PIPE_BUF is not declared (cygwin shows 512 for this). My SUSE Linux box shows 64K. Commented Jul 22, 2013 at 23:51
  • Thanks everyone. @rici's solution hit the nail exactly on the head, but I learned a lot about bash and pipes from your comments. Thank you! Commented Jul 23, 2013 at 11:11

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This was precisely the problem and this simple solution fixed everything! Thank you so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.