In class, we discussed the fact the all devices on a Unix system appear as files. These files support the usual open(), read(), write(), close(), lseek() interface we have seen when working with disk files.
How does that work in practice?
The code attached below is the printer driver for Linux. The file is called lp.c and is located in
/usr/src/linux/drivers/char/lp.cIt demonstrates two important facts:
To see how the standard file system operations are implemented. Look for the string lp_fops in the code below.
Each device creates a struct with pointers to functions for each of the standard operations. Think of it as an object with a set of methods. The methods are just the addresses of functions that perform each of the file operations.
In this case, the struct is defined as:
static struct file_operations lp_fops = { lp_lseek, #ifdef CONFIG_PRINTER_READBACK lp_read, #else NULL, #endif lp_write, NULL, /* lp_readdir */ NULL, /* lp_poll */ lp_ioctl, NULL, /* lp_mmap */ lp_open, NULL, /* flush */ lp_release };Each of those functions has an implementation in this lp.c file. Many printers are write-only devices, so the method for read() is either NULL or a call to lp_read(). At compile time, one can specify whether the lp driver is expected to be able to read from the printer.
The method for doing a device driver is:
Now, when a program tries to open that device file, the kernel will look in the struct and call the functions you have written. Pretty object-oriented.