The evolution of FreeBSD
FreeBSD has been around for ten years. During this time, it has evolved significantly, and it continues to evolve. In this chapter we'll look at what has changed, particularly in more recent times. If you're planning to install one of the older releases of FreeBSD, for example on old hardware that is too small for modern releases, refer to "Appendix A" , Bibliography, for copies of older editions of this book.
FreeBSD Releases 1 and 2
Release 1.0 of FreeBSD appeared in December 1993. It was substantially an improved and debugged version of 386/BSD, based on the 4.3BSD Net/2 tape. FreeBSD Release 2 was released in January 1995. The big difference from Release 1 was that it was based on 4.4 BSD Lite, one of the results of the lawsuit we discussed on page 8. There were no major differences from Release 1.
FreeBSD Release 3
FreeBSD Release 3.0 was released in September 1998. It represented the biggest change in FreeBSD since the code base was moved to 4.4BSD. A number of new features were introduced, which made upgrading a little more complicated than is normally the case. In particular, the following new features were of note:
- It introduced support for the Compaq/Digital Equipment AXP (also known as ALPHA) processor.
- On the Intel architecture, FreeBSD supported multiple processors.
- A new SCSI driver, CAM, was introduced. This required some modifications to the kernel configuration, and the device names changed. At present this means that FreeBSD device names are different from the NetBSD or OpenBSD names for the same devices. We'll look at CAM in more detail below.
- The IDE driver first supported DMA. We discussed DMA on page 32. The entire IDE driver was replaced in a later release.
- A new console driver was introduced.
- This release of FreeBSD started phasing out loadable kernel modules, described on page 163. Since then, theyhave been replaced by kernel loadable modules (klds). Does this sound likeword play? Well, there'sa solid technical background: you can tell the bootstrap to load kld salong with the kernel. We'll look at them below.
- A new, more flexible bootstrap (the program that loads the kernel) was introduced.
- The default object file format changed from a.out to TiLKFreeBSD supported the ELF format for some time previously, initially to emulate Linux, but now it is the native format as well. FreeBSD still supports a.out binaries.
The CAM SCSI driver
FreeBSD Release 3.0 included a new SCSI driver, based on the ANSI ratified Common Access Method or CAM specification, which defines a software interface for talking to SCSI and ATAPI devices. The FreeBSD driver is not completely CAM compliant, but it follows many of the precepts of CAM. More importantly, it addresses many of the short comings of the previous SCSI layer and provides better performance and reliability, and eases the task of adding support for new controllers.
For most users, the most obvious difference between the old SCSI driver and CAM is the way they named SCSI devices. In the old driver, disks were called sdn, and tapes were called stn, where n was a small positive number. The CAM driver calls disks dan (for direct access), and tapes are called san (for serial access).
In addition, a new program, camcontrol, enables you to administrate the SCSI chain at a more detailed level then previously: for example, it is now possible to add devices to a chain after the system has started. See the man page for more details.
Kernel loadable modules
Older releases of FreeBSD supplied Loadable Kernel Modules or LKMs, object files that could be loaded and executed in the kernel while the kernel was running.
The ELF kernel and the new bootstrap introduced with FreeBSD Release 3 allow you to load additional modules at boot time. To do so, however, the format of the modules needed to be changed. To avoid (too much) confusion, the name changed from loadable kernel module to kernel loadable module (kld).
Parameter | LKM | kld |
---|---|---|
Directory | /lkm | /boot/kernel |
Load program | modload | kldload |
Unload program | modunload | kldunload |
List program | modstat | kldstat |
Some other details have changed as well. kldload knows an internal path for finding klds, so you don't need to specify the path unless it's in a non-standard location. It also assumes that the name of the kld ends in .ko, and you don't need to specify that either. For example, to load the Linux emulator as an LKM, you entered:
# modload /lkm/linux_mod.o
# kldload linux
kldload searches for klds in a number of places. Table B-1 shows the default path, /boot/kernel. If you boot from a different kernel, for example /boot/kernel.old/kernel, the path will change to /boot/kernel.old. Up to Release 4 of FreeBSD, it searched /modules as well. At the time of writing, this directory is still in the search path, but it may be phased out. It's a bad idea to store kernel code where it might be loaded by different kernels.
The ELF object format
When UNIX was written, the world was simple. The kernel of the Third Edition of UNIX, in January 1973, had a little over 7,000 lines of code in total. The FreeBSD 5.0 kernel has approximately 300 times as much code. The original UNIX object format was correspondingly simple: it had provision for only three data segments. It was named after the name of the output from the assembler, a.out.
In the course of time, binaries required additional features, in particular the ability to link to dynamic libraries. UNIX System V introduced a new object file format, COFF, but BSD objected to some of the details of COFF and remained with a.out and used some rather dirty tricks to link to dynamic libraries. The change to ELF enabled a much cleaner interface.
Since Release 3, FreeBSD uses ELF as the default executable format, but the Intel port supported execution of a.out binaries until Release 5. The Alpha port was created after the change to ELF and does not support a.out at all.
What happened to my libraries?
One detail of the change from a.out to ELF can make life difficult: ELF and a.out executables need different libraries, each with their own format, but frequently with the same name. For example, the system now knows the following versions of the standard C library, which is required by every program:
- libc.a is a static library used for including the library routines into the program at link time.
- libc_p.a is a static library containing profiled versions of the library routines for inclusion into the program at link time.
- libc_pic.a is a static library containing position-independent versions of the library routines for inclusion into the program at link time.
- libcr.a is a static library containing reentrant versions of the library routines for inclusion into the program at link time.
- libc.so is a symbolic link to the current version of a dynamic library for linking at run time. This link is only used for ELF programs.
- libc.so.3 is a version of an ELF dynamic library for linking at run time. The number 3 changes with the release.
- libc.so.3.1 is a version of an a.out dynamic library for linking at run time. The number 3.1 changes with the release.
Don't worry if these names don't make much sense to you; unless you're writing programs, all you need to know is that an ELF system uses /usr/lib/libc.so at run time.
/usr/lib contains a large number of libraries. It would be possible, but messy, to find an alternative arrangement for the name contacts, and leave the rest of the names unchanged. Instead, the conversion process move sall a.out libraries to a subdirectory aout, so an a.out executable now looks for /usr/lib/aout/libc.so.3.0. An ELF executable looks for /usr/lib/libc.so.3.
But how does the system know to look in a different place? It uses a hints file generated by the ldconfig program. When the system starts, it takes a list of directory names from /etc/rc.conf and runs ldconfig to search the directories for a.out libraries and to generate the hints file. In Release 2 of FreeBSD, the standard /etc/rc.conf contained the following definition:
ldconfig_paths="/usr/lib/compat /usr/X11R6/lib /usr/local/lib" # search paths
In Release 3.0, this changed to:
ldconfig_paths="/usr/lib/compat /usr/X11R6/lib /usr/local/lib" #shared library search paths ldconfig_paths_aout="/usr/lib/compat/aout /usr/X11R6/lib/aout /usr/local/lib/aout" #a.out shared library search paths
Upgrading from Release 2 of FreeBSD
If you're still using Release 2, you might run into some minor problems. The following discussion applies when upgrading to Release 3 or anylater release: part of the upgrade process from Release 2 to Release 3 changes this entry in /etc/rc.conf so there should be no problem with normal libraries. A couple of problems may still occur, however:
- Some programs refer to library names that are symbolic links. The upgrade process doesn't always handle symbolic links correctly, so you may find that the link points to the wrong place. For example, you might have this in a 2.2.7 system /usr/lib/compat:
/usr/lib/compat: total 1 -r--r--r-- 1 root wheel 8417 Jan 21 18:37 libgnumalloc.so.2.0 -r--r--r-- 1 root wheel 8398 Jan 21 18:37 libresolv.so.2.0 lrwxr-xr-x 1 root wheel 31 Jan 21 18:36 libtermcap.so.3.0 -> /usr/lib/libte rmcap.so.2.1 lrwxr-xr-x 1 root wheel 31 Jan 21 18:36 libtermlib.so.3.0 -> /usr/lib/libte rmlib.so.2.1 -r--r--r-- 1 root wheel 8437 Jan 21 18:37 liby.so.2.0
After updating, you could end up with this:
/usr/lib/compat/aout: total 1 -r--r--r-- 1 root wheel 8417 Jan 21 18:37 libgnumalloc.so.2.0 -r--r--r-- 1 root wheel 8398 Jan 21 18:37 libresolv.so.2.0 lrwxr-xr-x 1 root wheel 31 Jan 21 18:36 libtermcap.so.3.0 -> /usr/lib/libte rmcap.so.2.1 lrwxr-xr-x 1 root wheel 31 Jan 21 18:36 libtermlib.so.3.0 -> /usr/lib/libte rmlib.so.2.1 -r--r--r-- 1 root wheel 8437 Jan 21 18:37 liby.so.2.0
In other words, the libraries have been moved, but the symbolic links are absolute and still point to the old place. The system doesn't install absolute symbolic links, so it doesn't make any attempt to correct them. You need to fix the problem manually. In this example, we replace the symbolic links with relative symbolic links:
cd /usr/lib/compat/aout rm libtermcap.so.3.0 ln -s libtermcap.so.2.1 libtermcap.so.3.0 rm libtermlib.so.3.0 ln -s libtermlib.so.2.1 libtermlib.so.3.0
- If you have modified your /etc/rc.conf significantly, the update may fail, and your a.out hints file will still point to the old locations. In this case edit /etc/rc.conf as shown above.
# cd /usr/X11R6/lib # mkdir aout # cp -p lib* aout