inter-process communication
Chris Torek
chris at umcp-cs.UUCP
Mon Feb 3 01:45:09 AEST 1986
I am not sure about 4.2, but SIGIO works in 4.3, at least judging by
the kernel code. But whether or not it works in 4.2 you will still
have to use a select loop in a signal handler, because (as you noted)
signals are not queued.
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#ifndef FD_ZERO /* 4.2, alas */
#define FD_ZERO(p) ((p)->fds_bits = 0)
#define FD_SET(n, p) ((p)->fds_bits |= 1 << (n))
#define FD_CLR(n, p) ((p)->fds_bits &= ~(1 << (n)))
#define FD_ISSET(n, p) ((p)->fds_bits & (1 << (n)))
#endif
int sockets[N]; /* for some N */
int nsockets;
...
signal(SIGIO, asyncinput);
...
/*
* Poll all the sockets to see who has input ready.
*/
asyncinput()
{
register int i, cc;
int nfds = 0;
fd_set inset, intemp;
struct timeval tv;
extern int errno;
/*
* Initialise `inset', then set bits for the descriptors
* in which we are interested. Also note the highest
* descriptor, and add one; this is the number of
* `interesting' descriptors in inset. (Passing an
* exact value helps the kernel run us faster.)
*/
FD_ZERO(&inset); /* init */
for (i = 0; i < nsockets; i++) {
FD_SET(sockets[i], &inset);
if (sockets[i] >= nfds)
nfds = sockets[i] + 1;
}
tv.tv_sec = 0; /* poll */
tv.tv_usec = 0;
/*
* Select until there is no more input available. Since
* select() clobbers its masks, we use a copy of inset.
* The select is done with a `poll' (time out immediately
* if nothing ready).
*/
for (;;) {
intemp = inset;
cc = select(max, &intemp, (fd_set *) 0, (fd_set *) 0,
&tv);
if (cc < 0) {
if (errno == EINTR)
continue;
/* handle select error */
}
if (cc == 0)
return; /* none left (timed out) */
for (i = 0; i < nsockets; i++)
if (FD_ISSET(sockets[i], &intemp))
readsocket(sockets[i]);
/* all done with input, try again for more */
}
}
Something like the above should work with explicit `kill's to wake
up readers as well as with SIGIOs from the kernel.
Oh, important: you must use F_SETOWN before you will get any SIGIOs:
me = getpid();
/* or -getpid() for process group instead of single owner */
for (i = 0; i < nsockets; i++)
if (fcntl(sockets[i], F_SETOWN, mypid))
oops(); /* handle error */
This is no doubt true in 4.2 as well. (You can substitute an
ioctl(SIOCSPGRP) for F_SETOWN, though I think the former is clearer.)
You may get a performance increase by setting the select timeout
to a few milliseconds, depending on how much message passing goes
on versus how much computation. Experiment a bit.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP: seismo!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at mimsy.umd.edu
More information about the Comp.unix.wizards
mailing list