|
Major and Minor Numbers
One of the basic features of the Linux kernel is that it abstracts the handling of devices.
All hardware devices look like regular files; they can be opened, closed, read
and
written using the same, standard, system calls that are used to manipulate
files.
Every device in the system is represented by a file.
For block (disk) and character devices, these device files are created
by the mknod command
and they describe the device using major and minor device numbers.
Network devices are also represented by device special files but they are
created by Linux as it finds and
initializes the network controllers in the system.
To UNIX,
everything is a file. To write to the hard disk, you write to a file. To read
from the keyboard is to read from a file. To store backups on a tape device is
to write to a file. Even to read from memory is to read from a file. If the file
from which you are trying to read or to which you are trying to write is a
"normal" file, the process is fairly easy to understand: the file is opened and
you read or write data. If, however, the device you want to access is a special
device file (also referred to as a device node), a fair bit of work needs to be
done before the read or write operation can begin.
One key aspect of
understanding device files lies in the fact that different devices behave and
react differently. There are no keys on a hard disk and no sectors on a
keyboard, though you can read from both. The system, therefore, needs a
mechanism whereby it can distinguish between the various types of devices and
behave accordingly.
To access a device accordingly, the
operating system must be told what to do. Obviously, the
manner in which the kernel accesses a hard disk will be different from the way
it accesses a terminal. Both can be read from and written
to, but that's about where the similarities end. To access each of these totally
different kinds of devices, the kernel needs to know that
they are, in fact, different.
Inside the kernel are
functions for each of the devices the kernel is going to access. All the
routines for a specific device are jointly referred to as the
device driver. Each device on the system has its own
device driver. Within each device driver are the functions
that are used to access the device. For devices such as a hard disk or
terminal, the system needs to be able to (among other
things) open the device, write to the device, read from the device, and close
the device. Therefore, the respective drivers will contain the routines needed
to open, write to, read from, and close (among other things) those devices.
The kernel needs to be told how to access the device.
Not only does the kernel need to be told what kind of
device is being accessed but also any special information, such as the
partition number if it's a hard disk or density if it's a
floppy, for example. This is accomplished by the
major number and
minor number of that device.
All devices controlled by the same device driver have a common major device
number.
The minor device numbers are used to distinguish between different devices and
their controllers.
Linux maps the device special file passed in system calls (say to mount a file
system on a block device) to the device's device driver using the major device
number and a number of system tables, for example the character device table, chrdevs.
The major number is actually the
offset into the kernel's device driver table, which tells
the kernel what kind of device it is (whether it is a hard
disk or a serial terminal). The minor number tells the
kernel special characteristics of the device to be accessed. For example, the
second hard disk has a different minor number than the
first. The COM1 port has a different minor number than the COM2 port,
each partition on the primary IDE disk has a different
minor device number, and so forth. So, for example, /dev/hda2, the second partition
of the primary IDE disk has a major number of 3 and a minor number of 2.
It
is through this table that the routines are accessed that, in turn, access the
physical hardware. Once the kernel has determined what kind
of device to which it is talking, it determines the specific device, the
specific location, or other characteristics of the device by means of the
minor number.
The major number for the hd (IDE) driver is hard-coded at 3.
The minor numbers have the format
(<unit>*64)+<part>
where <unit>
is the IDE drive number on the first controller, either 0 or 1, which is
then multiplied by 64. That means that all hd devices on the first
IDE drive have a
minor number less
than 64. <part> is the partition number, which can be
anything from 1 to 20. Which minor numbers you will be able to access will
depend on how many partitions you have and what kind they are (extended,
logical, etc.). The minor number of the device node that
represents the whole disk is 0. This has the node name hda, whereas the other
device nodes have a name equal to their
minor number (i.e., /dev/hda6 has a minor number 6).
If you were to
have a second IDE on the first controller, the unit number
would be 1. Therefore, all of the minor numbers would be 64 or greater. The
minor number of the device node representing the whole disk
is 1. This has the node name hdb, whereas the other
device nodes have a name equal to their
minor number
plus 64 (i.e., /dev/hdb6 has a minor number 70).
If you have more than
one IDE controller, the principle is the same. The only
difference is that the major number is 22.
For
SCSI devices, the scheme is a little different. When you
have a SCSI
host adapter, you can
have up to seven hard disks. Therefore, we need a different way to refer to the
partitions. In general, the format of the device nodes is
sd<drive><partition>
where sd refers to the
SCSI disk driver, <drive> is a letter for the
physical drive, and <partition> is the partition
number. Like the hd devices, when a device refers to the entire disk, for
example the device sda refers to the first disk.
The major number for all
SCSI drives is 8. The
minor number is based on the drive number, which is
multiplied by 16 instead of 64, like the IDE drives. The
partition number is then added to this number to give the
minor.
The partition numbers are not as simple to
figure out. Partition 0 is for the whole disk (i.e., sda). The four
DOS primary partitions are numbered 14. Then the extended
partitions are numbered 58. We then add 16 for each drive. For example:
brw-rw---- 1 root disk 8, 22 Sep 12 1994
/dev/sdb6
Because b is after the sd, we know that this is on the
second drive. Subtracting 16 from the minor, we get 6, which matches the
partition number. Because it is between 4 and 8, we know
that this is on an extended partition. This is the second
partition on the first extended partition.
The floppy devices have an
even more peculiar way of assigning minor numbers.
The major number is fairly easy its 2.
Because the names are a little easier to
figure out, lets start with them. As you might guess, the device names all begin
with fd. The general format is
fd<drive><density><capacity>
where <drive> is
the drive number (0 for A:, 1 for B:), <density> is the density (d-double,
h-high), and <capacity> is the capacity of the drive (360Kb, 1440Kb). You
can also tell the size of the drive by the density letter, lowercase letter
indicates that it is a i5.25" drive and an uppercase letter indicates that it is
a 3.5" driver. For example, a low-density 5.25" drive with a capacity of 360Kb
would look like
fd0d360
If your second drive was a high-density
3.5" drive with a capacity of 1440Kb, the device would look like
fd1H1440
What the minor numbers represents is a fairly complicated process. In
the fd(4) man-page there is an explanatory table, but it is
not obvious from the table why specific minor numbers go with each device. The
problem is that there is no logical progression as with the hard disks. For
example, there was never a 3.5" with a capacity of 1200Kb nor has there been a
5.25" with a capacity of 1.44Mb. So you will never find a device with H1200 or
h1440. So to figure out the device names, the best thing is to look at the
man-page.
The terminal
devices come in a few forms. The first is the system console, which are the
devices tty0-tty?. You can have up to 64 virtual terminals on you system
console, although most systems that I have seen are limited five or six. All
console terminals have a major number of 4. As we discussed
earlier, you can reach the low numbered ones with ALT-Fn, where n is the number
of the function key. So ALT-F4 gets you to the fourth virtual console. Both the
minor number and the tty number are based on the function
key, so /dev/tty4 has a minor number 4 and you get to it
with ALT-F4. (Check the console(4) man-page to see how to
use and get to the other virtual terminals.)
Serial devices can also
have terminals hooked up to them. These terminals normally use the devices
/dev/ttySn, where n is the number of the serial port (0, 1, 2, etc.). These also
have a minor number of 4, but the minor numbers all start at 64. (Thats why you
can only have 63 virtual consoles.) The minor numbers are this base of 64, plus
the serial port number (04). Therefore, the minor number of the third serial
port would be 64+3=67.
Related to these devices are the modem control
devices, which are used to access modems. These have the same minor numbers but
have a major number of 5. The names are also based on the device number.
Therefore, the modem device attached to the third serial
port has a minor number of 64+3=67 and its name is cua3.
Another device with a major number of 5 is
/dev/tty, which has a minor number of 0. This is a special
device and is referred to as the "controlling terminal. "
This is the terminal device for the currently running process. Therefore, no
matter where you are, no matter what you are running, sending something to
/dev/tty will always appear on your screen.
The pseudo-terminals (those
that you use with network connections or X) actually come
in pairs. The "slave" is the device at which you type and has a name like ttyp?,
where ? is the tty number. The device that the process sees is the "master" and
has a name like ptyn, where n is the device number. These also have a
major number 4. However, the master devices all have minor
numbers based on 128. Therefore, pty0 has a minor number
of 128 and pty9 has a minor number of 137 (128+9). The slave device has minor
numbers based on 192, so the slave device ttyp0 has a minor number
of 192. Note that the tty numbers do not increase numerically
after 9 but use the letter af.
Other oddities with the device numbering
and naming scheme are the memory devices. These have a major number of 1. For
example, the device to access physical memory is /dev/mem
with a minor number of 1.
The kernel
memory device is /dev/kmem, and it has a minor number of 2.
The device used to access IO ports is /dev/port and it has a
minor number of 4.
What about minor number 3? This is for device
/dev/null, which is nothing. If you direct output to this device, it goes into
nothing, or just disappears. Often the error output of a command is directed
here, as the errors generated are uninteresting. If you redirect from /dev/null,
you get nothing as well. Often I do something like this:
cat /dev/null
> file_name
This device is also used a lot in
shell scripts where you do not want to see any output or
error messages. You can then redirect standard out or standard error to
/dev/null and the messages disappear. For details on standard out and error, see
the section on redirection.
If file_name doesn't
exist yet, it is created with a length of zero. If it does exist, the file is
truncated to 0 bytes.
The device /dev/zero has a
major number of 5 and its
minor number is 5. This
behaves similarly to /dev/null in that redirecting output to this device is the
same as making it disappear. However, if you direct input from this
device, you get an unending stream of zeroes. Not the number 0, which has an
ASCII value of 48this is an ASCII 0.
Are those all
the devices? Unfortunately not. However, I hope that this has given you a start
on how device names and minor numbers are configured. The file
<linux/major.h> contains a list of the currently used (at least well
known) major numbers. Some nonstandard package might add a
major number of its own. Up to this point, they have been fairly good about
not stomping on the existing major numbers.
As far as the minor numbers
go, check out the various man-pages. If there is a man-page
for a specific device, the minor number will probably be
under the name of the driver. This is in major.h or often the first letter of
the device name. For example, the parallel (printer) devices are lp?, so check
out man lp.
The best overview of all the major and minor numbers is in
the /usr/src/linux/Documentation directory. The devices.txt is considered the
"authoritative" source for this information.
|