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.)
|
|