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