How major and minor device numbers worked in V7 Unix
Unix people who've been around for a while know that Unix devices
have device numbers, and that device numbers are divided into
major and minor device numbers. When you do 'ls -l /dev/null
'
and one of the fields that ls
prints is two comma separated
numbers, those are the major and minor numbers (on Linux, they are
'1, 3'; this varies by Unix). Device numbers and their split into
major and minor parts go back a long way, to before Research Unix
V7, but V7 makes a convenient point to look at what they meant and
how they worked in the original Unixes.
As various sources will tell you, the major number tells you (and
the Unix kernel) what sort of device it is and thus what device
driver to use to talk to it, while the minor number tells the device
driver what specific bit of hardware it's responsible for that you
want to talk to. Sometimes the minor number also determines some
bit of functionality. Because V7 was a deliberately simple and
brute force system and kernel, major device numbers had a very
simple implementation. We can see it in the generated V7 kernel
configuration file c.c
:
struct bdevsw bdevsw[] = { nulldev, nulldev, rkstrategy, &rktab, /* rk = 0 */ nodev, nodev, nodev, 0, /* rp = 1 */ [...] nodev, nodev, nodev, 0, /* hp = 6 */ htopen, htclose, htstrategy, &httab, /* ht = 7 */ nodev, nodev, nodev, 0, /* rl = 8 */ 0 };
What we're seeing here is that V7 literally had an array of bdevsw
structures indexed
by the major (block) device number, with various function that were
called when you did things like open a device (in fio.c
).
There was a similar array for character devices, the cdevsw
array.
In both of them, what driver functions were listed here instead of
stubbed out were determined by simple configuration files (here)
that said what devices you had (among other things).
(The c.c
file was generated by a program.
The particular c.c
file in the TUHS V7 tree was built with only
two block devices configured, the RK disk driver and
TJU16 tape driver 'ht'.)
In V7 the minor device number was only interpreted by the device
driver, as far as I can see. Device drivers used this for a variety
of purposes. For instance, the mem
character driver
implemented /dev/null
as minor device 2, to go along with access
to physical memory and kernel memory. The rl
disk driver used
the minor device number to decide what physical disk it was talking
to (it supported up to four of them). Once V7 started getting out
in the world, other people wrote drivers for it (such as the RX02
floppy disk driver) that
used minor device numbers both to select what to talk to and control
what features to use.
(There's also the kl
KL/DL-11 serial and console driver, which
seems to deal with three different sets of hardware control registers
based on the minor number.)
The /dev/tty
character device was implemented in a clever and
very short way in sys.c
. In
V7, there were no pseudo-ttys and no hot-plugged devices, so your
underlying physical terminal device always existed and was recorded
in your u
area (see user.h
) The
general tty driver simply used this recorded device number of your
controlling tty to call its open, read, write, and ioctl functions
through the cdevsw
array. As far as I can tell, this driver paid
no attention at all to the minor device number; as long as /dev/tty
had major number 7, the minor number was irrelevant.
PS: Note that V7 device drivers tended to be a little relaxed about
error checking for their minor device numbers (and other things).
For instance, as far as I can tell the mem
driver actually only
distinguishes between minor number 2, minor number 1, and 'everything
else', which is treated as minor number 0, giving access to physical
memory.
Comments on this page:
|
|