08-19-04 12:48 PM
shellcode wrote:
> i wrote a program to control a device attached to the serial port of
> my computer. the program works fine but it is meant to work together
> alongside with other programs. at first i was just going to have the
> other programs run the control program. this would work fine but then,
> i thought that a more elegant solution would be to have the other
> programs communicate with this one through UNIX IPC.
>
> what i need to know is what type of IPC would be best. my control
> program would only need to receive short messages (~5 bytes) and then
> control the serial port based on those messages. i was thinking that a
> message queue would be best but perhaps one of the experts here feels
> that a shared memory segment or a FIFO would be better?
Hi,
Last year I've made a trivial device connected to the serial port. It
has 2 LED's and a pushbutton. The two LED's can be switched on/off
serperately. When the button is pressed, both are switched off (by the
program). I have made a contruction similar to what you mention, which I
run on Linux.
The LED's are on the RTS an DTS lines, so when the controlling program
exists, they are switched off. This is not what I want, so I needed to
run the controlling program as a daemon, and have a client program that
just sends the daemon messages (specified by the command line options)
to switch on or off a specified LED. It waits for acknowledgement and
exits as soon as possible.
Without activity, the daemon has /dev/ttyS0 open and waits sleeping for
the pushbutton to be pressed. It listenes sleeping for the CTS line to
change by calling:
ioctl(fd, TIOCMIWAIT, mask) == -1) {
if (errno == EINTR) {
/* interrupted, need to read message from queue */
/* ... */
When the client wants a LED to be turned on, it puts a (tiny) message on
a message queue, and sends SIGUSR1 to the daemon to wake the daemon
up. The dameon will then pick up the message, turn LED on/off
accordingly, return an acknowledge message via the same message queue,
and resume listening for the button again as soon as possible.
To prevent receiving too much SIGUSR1's than the daemon can handle, and
prevent the message queue from overflowing, I use a basic semaphore
mechanism. I don't have much experience with this kind of stuff, but it
seems to work quite good. When starting as much clients as possible,
all these processes keep running waiting for the semaphore to become
available. And all get processed after some time. Drawback is that
this way (many client requests waiting to be processed) the order of the
message to arrive at the LED's is not guarantined to be the same as the
order in which the clients were started. But in my case this doesn't
matter really.
To prevent multiple daemons started for the same serial port, the dameon
locks a file in /tmp which has the device name of the serial port
included in its file name. fnctl() is used for the lock. These
fcntl-locks also enable clients to get the PID of the daemon.
I was planning to put it on some website, but I have yet to do that...
However, if you are interested, drop me an e-mail, and I'll send you the
tarball (GPL'd).
Regards,
Heiko
[ Post a follow-up to this message ]
|