/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