NEXT UP previous
Next: Interrupts

Special Control Functions

In addition to the basic open, close, read and write operations, you have also seen that sometimes it is desirable to send control information to the device driver or to take status information from it. For example, changing the baud rate on a serial port does not lend itself to being performed by the basic open, close, read, write paradigm. In this case (and many others like it) you have seen that the solution is to use the ioctl() system call. This system call is implemented by just calling an ioctl() function in the device driver to deal with it.

This is necessary because different device drivers will not all want to implement the same functions - there are many devices for which trying to change the baud rate would make no sense.

The device driver ioctl() function has the prototype:

	int ioctl(struct mode *inode, struct file *file, unsigned int cmd, unsigned long arg);

where mode and file are the same as before, cmd is a device driver specific code for the command to be performed and arg is any kind of 4-byte thing (typically an int or a struct *) which provides a parameter for the particular cmd value. The cmd and arg parameters are obtained from the second and third parameters to the ioctl() system call.

Don't forget that if the arg parameter is a pointer to a block of memory in user space then you must use the special copy functions we looked at earlier to put and get values to and from this memory block.

In general, you are free to use any numbers you wish for cmd values, except that Linux uses four special values which it interprets before your ioctl() routine gets called:

FIONBIO0x5421set/reset O_NONBLOCK from arg;
FIONCLEX0x5450clear close-on-exec flag;
FIOCLEX0x5451set close-on-exec flag;
FIOASYNC0x5452set/reset O_SYNC from arg.

If you use any of these four cmd values for your own ioctl() commands then your routines will never be called because the kernel gets to them first.


NEXT UP previous
Next: Interrupts