Skip to main content

Common threads: Advanced filesystem implementor's guide, Part 4

Introduction to devfs

Daniel Robbins (drobbins@gentoo.org), President/CEO, Gentoo Technologies, Inc.
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.

Summary:  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.

Date:  01 Sep 2001
Level:  Introductory
Activity:  1890 views

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.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux, Open source
ArticleID=11152
ArticleTitle=Common threads: Advanced filesystem implementor's guide, Part 4
publish-date=09012001
author1-email=drobbins@gentoo.org
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers