2015-06-29
BSD Unix developed over more time than I usually think
Left to myself, I tend to sloppily think of 4.2 BSD as where all of the major development of BSD Unix took place and the point in time where what we think of as 'BSD Unix' formed. Sure, there were BSDs before and after 4.2 BSD, but I think of the before releases as just the preliminaries and the releases after 4.2 BSD as just polishing and refining things a bit. As I was reminded today, this view is in fact wrong.
If you'd asked me what 4.x BSD release inetd
first appeared in, I
would have confidently told you that it had to have appeared in 4.2 BSD
along with all of the other networking stuff. Inetd is such a pivotal
bit of the BSD networking (along with the services that it enables,
like finger
) that of course it would be there from the start in 4.2,
right?
Wrong. It turns out that inetd
only seems to have appeared in 4.3
BSD. In fact a number of related bits of 4.2 BSD are surprisingly
under-developed and different from what I think of as 'the BSD way'.
Obviously, finger
in 4.2 BSD is not network enabled, but a more
fundamental thing is that 4.2 BSD limits processes to only 20 open
file descriptors at once (by default, and comments in the source
suggest that this cannot be raised above 30 no matter what).
Instead it is 4.3 BSD that introduced not just inetd
but a higher
limit on the number of open file descriptors (normally 64).
With that higher limit came the modern FD_*
set of macros used
to set, check, and clear bits in the select()
file descriptor
bitmaps; 4.2 BSD didn't need these since the file descriptor masks
fit into a single 32-bit word.
(I discovered this due to a Twitter conversation with Mark Jason Dominus. I now think my initial answer is almost certainly wrong, but that's going to be another entry.)
Sidebar: dup2()
and BSD's low file descriptor limit
Given the existence of the dup2()
system call, which in theory
lets you create a file descriptor with any FD number, you might
wonder how 4.2 BSD got away with a 32-bit word for the select()
bitmask. The answer turns out to be that 4.2 BSD simply forbid you
from dup2()
'ing to a file descriptor number bigger than 19 (or
in general the NOFILE
constant).
(You can see the code for this in the dup2()
implementation.
In general a lot of the early Unix kernel source code is quite simple
and readable, which is handy at times like this.)