Wandering Thoughts archives

2011-10-19

Defending Berkeley's forced choice in network device naming

Despite what I wrote back in the last entry, I actually think that BSD's choice to not put network devices in the filesystem is defensible and in many ways was the best option they had. Explaining why requires rewinding back to the pre-BSD days of Unix.

In the days of V7 and earlier, devices on Unix were simple. You had block special devices for hardware like hard drives that you read from and wrote to in fixed size blocks, and character special devices for hardware such as serial ports that you could do IO to either a character at a time or (sometimes) in variable block sizes. When you needed to manipulate parameters of the hardware like the serial port speed, you generally garnished this basic model with some ioctl()s, although some drivers used other schemes to distinguish what you wanted.

(The tape drivers famously used portions of the device minor number to say whether or not you wanted the drive to rewind automatically and what block size they should use. This led to a profusion of /dev/*mt0* names with subtly different semantics that gave sysadmins exciting times for years.)

What this model doesn't cope well with is what I'll call 'control' devices, devices that you use to manipulate parameters instead of reading and writing data. The traditional approach was to make such things character devices so that you could open them and then use a lot of ioctl()s for the actual controlling, but this had various issues (ioctl()s are sort of the magic escape hatch of Unix, but they have limits). You can fit such control devices into the Unix approach, but the insights and infrastructure for doing it just weren't there in the early 1980s when BSD was being developed; in the end it would take most of a decade before the Bell Labs people fully developed it in Plan 9.

(It is worth remembering that in 1980, there was no idea of a 'virtual filesystem layer' that unified disparate filesystem types; there was just the filesystem, singular and period. Sun implemented the first Unix VFS in the mid 1980s for NFS.)

So there is the Berkeley CSRG, designing the BSD network layer and realizing that they needed network devices. Network devices (in the sense of things like eth0) are clearly not block devices and they are not really character devices either; you don't do IO to them, you use them to control things. CSRG could have implemented them as character devices with a heaping helping of ioctl()s, but that would have been ugly and it would probably also have eaten up a good chunk of the limited character device address space (probably too much of it).

So the CSRG had two real choices. If they wanted network devices to live in the filesystem, they were going to have to add a third type of device (either 'network devices' or 'control devices'). This would have required changes all over the system, from the filesystem up through the kernel to utilities and even things like ls and test. This would obviously be a lot of work, and it would get you very little for that work.

Or CSRG could give network devices an entirely independent namespace, outside of the filesystem. The only programs that would have to know about this namespace were network management programs (which CSRG had to write anyways).

In hindsight, I'm not too surprised that CSRG decided to take the second option. You can criticize them for deviating from the spirit of Unix in this (as they did with any number of other things), but on the other hand in many ways they were under very business-like pressures to deliver results in the form of a Unix with networking.

(After all, that's what they'd gotten grants to do. DARPA did not fund CSRG to conduct leading edge research on how to integrate networking into the fundamental Unix vision; they funded CSRG to get IP into a version of Unix. Or such is my understanding, at least.)

Sidebar: why having actual control devices doesn't get you much

Since you can't do regular IO to 'control' devices, you can't leverage other Unix tools to work with them. The drawback of using ioctl()s is that every ioctl() is custom; there is no such thing as a general ioctl()-manipulation program the way that, say, awk is a general text stream processor. Despite being in the filesystem, a control device can only be manipulated with dedicated management commands.

This may be one reason that Research Unix did not have a separate category for such 'control' devices to start with.

(To a certain extent V7 used plain read() and write() to control devices, but from a skim of some V7 manpages it seems as if it was for devices that needed somewhat less extensive control than network devices.)

unix/BSDForcedNetworkNaming written at 01:18:40; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.