An alternative solution: software handshaking
If you send a control-S (XOFF) to the Linux side, it will stop sending output. Send a control-Q (XON) to restart it.
The general idea is that you monitor how many characters are already in the serial buffer (Serial.available())
The standard way of doing this is to have two threshold values: high-water and low-water. When the number of characters already in the buffer reaches or exceeds the high-water mark, the buffer is getting too full so send the XOFF character to stop the incoming data flow. As the buffer is drained by your output process, when the number of characters in the buffer reaches or falls below the low-water mark, then the buffer has enough room, so send the XON character to resume receiving data.
The proper values for the high-water and low-water thresholds will depend on the size of the data buffer, how quickly the sending process (Linux in this case) responds to the XON/XOFF, the communications baud rate, and how often you are checking the available space.
Normally, when I implement something like this, I'm handling it in a serial data receive interrupt routine. That means I can check the available space on each incoming character (and not have to poll the free space) and I can respond very quickly if getting full. In this case, I can usually set the high-water mark very close to the end of the buffer.
With the Arduino Serial library, where you don't have direct access to the serial interrupt, you will have to frequently poll Serial.Available() for the amount of space used. In this case, you will probably have to set your high-water mark lower. You want to make sure that the number of characters that could possibly be received between polls is less than the amount of room in the buffer.
For example, at 250000 baud, it takes about 0.04 milliseconds (40 microseconds) to transmit a character. That means a 64 character buffer can fill up in 2.5 ms. That's not much time! In practical terms, you would probably want to poll the available space about every millisecond, and set your high-water mark so that you leave a good 50 (or even 60?) characters of space.
To do this, you will probably need to poll Serial.Available() on every pass through loop(), and keep the other processing in loop() as short as possible, using the "BlinkWithoutDelay" concepts to maintain any required timing. Calling delay() inside of loop() will cause serious problems (unless you only do it when you sure that output has been stopped by XOFF.)
In fact, now that I've said that last sentence, maybe a workable scheme would be: (psuedocode, not compilable)
void setup()
{
setup the serial port
send an XOFF character to Linux
}
void loop()
{
if (serial.Available())
{
read a character and process it.
doesn't really matter how long it takes.
}
else
{
// No data is available
send XON character to Linux
delayMicroseconds(500)
send XOFF chacracter to Linux
}
}
The idea is that normally the character flow is stopped. If there is no data available, start the flow, wait a short time (less time than it could possibly take to fill the buffer) and then stop the flow. Process characters as long as something is there, and once empty start the flow for a short time to get another chunk of data to work on.
It's kind of a messy way to do it, and it's not the most efficient way to get high throughput. But without access to the serial data interrupt, it's a rather safe way to make sure you don't get overruns, and from the sound of your mechanical output device, it doesn't sound like throughput is a major concern.