 | Level: Introductory Daniel Robbins (drobbins@gentoo.org), President/CEO, Gentoo Technologies, Inc.
01 Sep 2001 With the 2.4 release of Linux come a host of new filesystem possibilities, including Reiserfs, XFS, GFS, and others. These filesystems sound cool, but what exactly can they do, what are they good at, and exactly how do you go about safely using them in a production Linux environment? Daniel Robbins answers these questions by showing you how to set up these new advanced filesystems under Linux 2.4. In this installment, Daniel explains the significance and benefits of devfs, the device management filesystem, getting you ready for the next article where he'll show you how to optimally set up devfs on your system. Introducing devfs
Devices, devices everywhere
Devfs, also called the Device Filesystem, is designed with the single purpose
of giving us a new (and more sane) way to manage all the block and character
devices that normally populate /dev. As you probably know, a
typical /dev tree contains hundreds of block and character special
files, all of them sitting on your root filesystem. Each of these special
files allow for user-space processes to easily interact with kernel devices.
By performing operations on these special files, your X server is able to
access your video hardware, fsck can perform filesystem checks and
lpd is able to send data through the parallel port to your printer,
for example.
In fact, one of the cooler things about Linux and Unix in general is that our
devices aren't simply hidden away behind some obscure API, but actually exist
on filesystem proper, alongside normal files, directories and symbolic links.
Because our character and block devices are mapped into our normal filesystem
namespace, we're often able to interact with our hardware in meaningful ways
simply by using standard Unix commands, such as cat and dd.
Besides being fun, this us to have more expressive power, which in turn allows
us to be more productive.
Device management problems
However, while device special files are a good thing in themselves, typical
Linux systems manage these special files in a suboptimal and cumbersome way.
These days, Linux supports a lot of different kinds of hardware. This
means that most of us have literally hundreds of special files in
/dev to represent all of these devices. Not only that, but most
of these special files don't even map to a existing device on our system (but
they need to be there just in case we eventually add new hardware/drivers to
our system), making things even more confusing.
From just this one aspect, we can see that /dev is in need of an
overhaul, and devfs was created with the express purpose of whipping
/dev back into shape. To get a good understanding of how devfs
solves the vast majority of /dev management problems, let's take a
look at devfs from the perspective of the device driver.
Device management internals
To get a good understanding of devfs, it's best to first understand how devfs
changes things from the perspective of the device driver. Traditionally
(without devfs), a kernel-based device driver registers a device with the rest
of the system by calling either register_blkdev() or
register_chrdev(), depending on whether it is registering a block
or character device.
A major number (an unsigned 8-bit integer) must be provided as an
argument to either register_blkdev() or register_chrdev(); then,
after the device has been registered, the kernel will understand that this
particular major number corresponds to the particular device driver that
performed the register_???dev() call.
So, what major number does the device driver developer supply with the
call to register_???dev()? Well, if the developer doesn't plan to share
the device driver with the outside world, then any number will do, as long as
it doesn't conflict with any other major numbers used by his or her current
kernel. Alternatively, the developer could opt to have a major number
dynamically assigned to the driver by the register_???dev() call.
However, these solutions are normally only feasible if the driver won't be used
by anyone else.
Take a number
However, if the developer wants to share the driver with the rest of the world
(and most Linux developers tend to take this approach), then simply pulling a
major number out of thin air or using dynamic major number allocation won't
work. Instead, the developer must contact the Linux kernel developers so that
his or her particular device can be assigned an "official" major number. Then,
throughout the Linux world, this particular device (and only this
device) will be associated with this particular major number.
It's important to have an "official" major number because, in order to interact
with this particular device, the administrator must create a special file in
/dev. When the device node (special file) is created, it must
sport the exact same major number that is used internally by the kernel. That
way, when a process performs an operation on the device, the kernel knows what
device driver should be referenced. The mapping from special file to kernel
driver is made possible by the major number, not the actual device name, which
is irrelevant to a non-devfs system.
Once a device driver has an official major number, the device can be used
publicly, and the device node can start to become incorporated into the various
distributions' /dev tree, as well as their offical
/dev/MAKEDEV script, a special script used to assist the superuser in
creating device nodes with the correct major and minor numbers, permissions and
ownership.
Traditional problems
Unfortunately, there are lots of scalability problems with this kind of
approach. Not only is it a pain for the device driver developer to contact
the kernel developers in order to receive an official major number, but it
must be even more annoying for the kernel developers to keep track of how
they've allocated all these major numbers. In many ways, this task is a lot
like the sysadmin's job of tracking the allocation of static IP addresses
on a company LAN -- it's not too fun. And just like the sysadmin can take
advantage of DHCP to ease this administration burden, it would be nice if
there were some similar approach for registering devices.
Not only that, but Linux is running out of major and minor numbers. While this
problem could be solved by simply expanding the number of bits used for major
and minor numbers, it's already a pain to maintain these major number mappings
in the first place, so again, one wonders if there is a better way to do
things. Fortunately, there is; enter devfs.
Enter devfs
devfs_register()
Here's a quick rundown of how devfs does its thing and solves all these
problems in one fell swoop. Once devfs is configured correctly, which involves
adding devfs support to the kernel as well as performing a number of
semi-tricky changes to startup scripts, the superuser reboots the system.
Then, the kernel starts to boot and device drivers begin to register devices
with the rest of the system. You'll recall that on a non-devfs system, the
register_blkdev() and register_chrdev() calls (along with
supplied major numbers) are used for this purpose. However, now that devfs is
enabled, the device drivers use a new and improved kernel call to register
their devices, called devfs_register().
Here's what's interesting about the devfs_register() call. While it's
possible to specify a major and minor number as arguments for compatibility
purposes, this is no longer required. Instead, the devfs_register()
call accepts the path to the device as it should appear under
/dev as an argument. For example, let's say that the
foo device driver wants to register a device with devfs. It would
supply an argument of foo0 to devfs_register(), thus telling the
kernel that a new foo0 device should be created at the root of the devfs
namespace. In response, devfs_register() adds the foo0 device
node to the root of the devfs namespace, and records that this new foo0
node should map to the foo device driver in the kernel.
Devfs in action
Once all device drivers have started up and registered the appropriate devices
with the kernel, the kernel starts /sbin/init and the system
initialization scripts begin to execute. Early in the boot process (before
filesystem checks), the rc scripts mount a devfs filesystem to
/dev, which contains a representation of the devfs namespace.
This means that after /dev is mounted, all registered devices (such
as /dev/foo0, above) can be accessed just as one would on a non-devfs
system. When they are accessed, the kernel maps to the appropriate device
driver by devfs device name, rather than by major number.
The beauty of this system is that all required device nodes (and no more) are
created automatically by the kernel. Not only does this mean that
MAKEDEV is no longer needed (since all registered devices simply
"appear" in /dev), but it means that /dev is no
longer cluttered with hundreds of "dud" device nodes. In fact, with devfs, you
can simply look in /dev to see what devices are on the system.
So, if you have a laptop with hotplug support, this means that you can even
have devices magically appear and disappear from /dev as you
insert and remove PC Cards from your system. This makes devfs a very clean and
functional solution to something that was previously an unweildly mess.
The beauty of devfs
Devfs makes a lot of things much easier. Consider the challenge of
creating a Linux bootable CD-ROM, which consists of a boot loader, an initrd, a
kernel, and a loopback filesystem sitting on the CD. When the CD boots, the
boot loader loads the kernel and the initrd, and then the /linuxrc
script on the initrd is then executed by the kernel. /linuxrc's primary
task is to get the CD mounted so that the loopback filesystem can itself be
mounted and accessed.
Without devfs, linuxrc needs to "probe" a number of special files in
/dev that may or may not represent actual hardware that is
connected to the system. For example, linuxrc will need to scan
/dev/hdc, /dev/scd0, /dev/hdb and other
devices in order to detect the "live" CD-ROM device. Along the way, it's very
likely that it will hit several "dud" device nodes.
However, with devfs, linuxrc simply looks in /dev/cdroms,
which contains all special files associated with the active CD-ROMs in
the system, whether IDE or SCSI. Thanks to this handy new devfs convention,
there's no more guessing; only active devices are listed, and the device
probing code doesn't even need to concern itself about the particulars of the
underlying CDROM, such as what IDE channel or SCSI ID it uses. In fact, this
is another major benefit of devfs; as we'll see in my next article, devfs has
completely new default locations for devices in /dev.
In fact, when you want to access a particular block device (such as a disks,
partition, CD-ROM drive, etc) you'll actually have several different
special files to which you can refer. For example, my server has a single SCSI
CD-ROM; with devfs enabled, I can access it by mounting either
/dev/cdroms/cdrom0 or
/dev/scsi/host0/bus0/target4/lun0/cd. Both refer to the same
device, and I can refer to the special file that I find most convenient. I can
also access my CD-ROM using an old-style device name (/dev/sr0) if
I like, thanks to a very handy little program called devfsd.
devfsd is an extremely versatile program that takes care of creating
old-style "compatibility" special files, and also allows you to customize
/dev in a tremendous number of ways. We'll take a close look at
devfsd in my next article, when I guide you through the process of
getting devfs up and running on your own system. Until then, check out the
following resources for more information about devfs:
Resources
About the author  | |  |
Residing in Albuquerque, New Mexico, Daniel Robbins is the President/CEO of Gentoo Technologies,
Inc., the creator of Gentoo Linux, an advanced Linux for the
PC, and the Portage system, a next-generation ports system for Linux.
He has also served as a contributing author for the Macmillan books
Caldera OpenLinux Unleashed, SuSE Linux Unleashed, and Samba Unleashed.
Daniel has been involved with computers in some fashion since the
second grade, when he was first exposed to the Logo programming
language as well as a potentially dangerous dose of Pac Man. This
probably explains why he has since served as a Lead Graphic Artist at
SONY Electronic Publishing/Psygnosis. Daniel enjoys spending
time with his wife, Mary, and his daughter, Hadassah. You can contact Daniel at drobbins@gentoo.org. |
Rate this page
|  |