I find myself having to use multiple serial ports for my home data acquisition software. One of the problems with that is that the acquisition program needs to have exclusive access to the serial port: If someone uses
So I need a way to lock a serial port: Once a program starts using it, it needs to make sure no other program will touch it. This is an absolutely standard and boring problem, and there are three known solutions to it:
Footnote 1: Clearly, you can't guard against
Footnote 2: There is another problem which needs to be solved, which makes solving this locking problem even more important: Since I have multiple devices connected via serial port (mostly using USB-to-serial adapters), I have no idea a priori which /dev/ttyXX file corresponds to which piece of hardware (water sensor, pressure controller, lighting interface, pump controller ModBus interface, ...). All these things use different baud rates, and different protocols. The way to identify the one you are looking for is: Promiscuously loop over all serial devices, set them to the desired baud rate, and send a "who are you" or "are you there" command using the desired protocol. If you get a syntactically correct response with the right ID number, you win. If you get nothing, or complete gibberish, you check the next one. The problem with this is: Whenever a program needs to find its hardware, it will send "garbage" to many devices, which those devices won't know how to interpret, or which will screw up the protocol for the real user of that other device. So once a program finds the correct serial device, it really should lock it, to prevent other programs from wasting their time on checking it, and perhaps breaking its own communication.
cu
or minicom
or even just cat /dev/ttyXX | hexdump -C
while my software is running, bad things happen. (I'll add a footnote below to explain why this problem is worse than one thinks, and can't just be solved with discipline).So I need a way to lock a serial port: Once a program starts using it, it needs to make sure no other program will touch it. This is an absolutely standard and boring problem, and there are three known solutions to it:
- Use a lock file: When you open /dev/ttyXX, you also create /var/lock/LCK..ttyXX, and there is a well-known technique of what should be written into that lock file. The lock file gets deleted when the program stops using the serial port. All programs need to check for that lock file before touching a port.
- Use standard Unix advisory file locking: Call flock()(2) and friends before and after using the device file. Note that this is advisory only, and again requires cooperation from all programs that use serial ports.
- When opening the device, change its ownership and permission so no other process can use it, and change it back when done. This works badly, because it doesn't help against root. And again, it only works if all programs cooperate (and this technique has other problems too).
Footnote 1: Clearly, you can't guard against
cat /dev/ttyXX >...
or cat foo.txt > /dev/ttyXX
, since the cat program doesn't use any locking, but that should be a rare abuse that we can ignore.Footnote 2: There is another problem which needs to be solved, which makes solving this locking problem even more important: Since I have multiple devices connected via serial port (mostly using USB-to-serial adapters), I have no idea a priori which /dev/ttyXX file corresponds to which piece of hardware (water sensor, pressure controller, lighting interface, pump controller ModBus interface, ...). All these things use different baud rates, and different protocols. The way to identify the one you are looking for is: Promiscuously loop over all serial devices, set them to the desired baud rate, and send a "who are you" or "are you there" command using the desired protocol. If you get a syntactically correct response with the right ID number, you win. If you get nothing, or complete gibberish, you check the next one. The problem with this is: Whenever a program needs to find its hardware, it will send "garbage" to many devices, which those devices won't know how to interpret, or which will screw up the protocol for the real user of that other device. So once a program finds the correct serial device, it really should lock it, to prevent other programs from wasting their time on checking it, and perhaps breaking its own communication.