/dev/null

tim at ISM780B.UUCP tim at ISM780B.UUCP
Wed Nov 27 09:00:00 AEST 1985


All IO system calls eventually end up as a call to a device driver.
Which driver is determined by the major device number, via a table
called bdevsw[] for block devices, and cdevsw[] character devices.

The items in these tables are structures that contain, among other
things, pointers to the routines to handle read and write ( for
character devices ), or a routine called the strategy routine ( for
block devices ( this is sort of a combined read and write routine ) ).

When the routine for the device driver is called, it is given the minor
device number, which it uses in whatever way it wants.  A typical device,
such as a magtape, will use some bits of the minor device number to
determine which of several tape drives to use, and the other bits to
indicate things like density, write-enable, or whatever.

It is the job of the device driver to transfer the data to/from the
device.  Let's concentrate on character devices ( like /dev/{null,mem,
kmem} ).  When the read or write routine is called, u.u_base will point
to the data to transfer, u.u_count will tell how may bytes to transfer,
and u.u_segflg will tell if u.u_base is a kernel address or a user address.
u.u_offset tells where in the device to read/write from/to.

For /dev/{mem,kmem,null}, the write routine looks something like this:

mwrite( minor )
{
	switch ( minor ) {
	case KMEM:
		/*
		 * verify that the requested address is part of kernel
		 * memory, make sure that the user address is in the
		 * users address space.  Transfer the data.
		 */
		break;
	case NULL:
		u.u_offset += u.u_count;        /* ?not sure */
		u.u_count = 0;          /* means all data xfered */
		break;
	case MEM:
		/*
		 * a lot like KMEM
		 */
}

Note that to most of the kernel, this looks just like a write to any
other character device, such as a line printer.  The sequence from
the system call to the device goes something like this:

	1. you do a write system call
	2. UNIX figures out it is a write system call
	3. Sets up u.u_base, u.u_count and u.u_segflg
	   from yur parameters to write
	4. uses the file descriptor you gave it to find out the inode
	5. notes that inode is for a character device
	6. gets the major and minor device number from the inode
	7. Does something like
		(*cdevsw[ major ].write_routine)( minor );

Block devices are very similar, except that they are given a pointer
to a buffer to transfer, and the system will not call the device if the
data is in the buffer cache.

					Tim Smith
					ima!ism780!tim
					ihnp4!cithep!tim



More information about the Comp.unix.wizards mailing list