ioctl

Rob Warnock rpw3 at rigden.wpd.sgi.com
Thu May 23 13:48:46 AEST 1991


In article <1991May22.161432.25064 at murdoch.acc.Virginia.EDU>
acl3k at jade.cs.Virginia.EDU (Allan Christian Long) writes:
+---------------
| The problem is that the prototype for ioctl is
| 	int ioctl (int fildes, int request, ...);
| That says what the first and second parameters should be, but I need to
| find out about the rest, which are dependent upon what request is.  The
| entry for FIONREAD in ioctl.h is
| 	#define FIONREAD _IOR(f, 127, int)      /* get # bytes to read */
| I tried changing charToRead to an int, but that didn't help.  I need
| documentation for FIONREAD, more than what it says in the header file.
+---------------

The third arg for FIONREAD is the *address* of an integer, that is:

	int num_bytes_avail_to_read;

	err = ioctl(file_descriptor, FIONREAD, &num_bytes_avail_to_read);

Note that the number of bytes actually avilable to read without blocking
may change (increase) between the time you do the FIONREAD and the time you
actually do the read(). For this reason, I never use the return value
(in "num_bytes_avail_to_read", above) for anything but a binary flag to
say there's something available to read without blocking. I do the read
full-sized and use the return value from the read() to say how much was
actually there:

	int n;
	char buf[BUFSIZ];	/* or whatever size */

	if (ioctl(s, FIONREAD, &n) < 0) {    /* "s" is the file descriptor */
		...handle error...
	}
	if (n > 0) {
		n = read(s, buf, sizeof buf);
		if (n < 0) {
			...handle error...
		}
		...
	}

If this is all you are using FIONREAD for, you can alternatively use select(2),
though a bit more awkwardly:

     #include <sys/types.h>
     #include <sys/time.h>

	fdset in_set;
	struct timeval t0;
	int err;

	t0.tv_sec = 0;
	t0.tv_usec = 0;
	FD_ZERO(&in_set);
	FD_SET(s, &in_set);
	err = select(s + 1, &in_set, (fd_set *)0, (fd_set *)0, &t0);
	if (err < 0) {
		...handle error...
	}
	if (FD_ISSET(s, &in_set)) {
		n = read(s, buf, sizeof buf);
		if (n < 0) {
			...handle error...
		}
		...
	}

Of course, if there is only one file descriptor being polled, as in the
example above, the return value from the select() can be checked (err > 0)
instead of the FD_ISSET(). But using FD_ISSET() generalizes nicely to
multiple-channel polls:

	err = select(...)
	if (err < 0) {
		...handle error...
	}
	if (err > 0) {		/* SOME channel is ready */
		if (FD_ISSET(fd1, &in_set)) {
			n = read(fd1, ...);
			...
		}
		if (FD_ISSET(fd2, &in_set)) {
			n = read(fd2, ...);
			...
		}
		...and so on...
	}


-Rob

-----
Rob Warnock, MS-1L/515		rpw3 at sgi.com		rpw3 at pei.com
Silicon Graphics, Inc.		(415)335-1673		Protocol Engines, Inc.
2011 N. Shoreline Blvd.
Mountain View, CA  94039-7311



More information about the Comp.sys.sgi mailing list