Опубликован: 06.08.2012 | Доступ: свободный | Студентов: 1331 / 47 | Оценка: 5.00 / 5.00 | Длительность: 53:41:00
Лекция 33:

Custom kernels

Building and installing the new kernel

The traditional way to build a BSD kernel was, assuming a configuration file called FREEBIE:

# cd /usr/src/sys/i386/conf
# config FREEBIE
# cd ../compile/FREEBIE
# make depend all install

At the time of writing, this still works, but it will go away at some time in the future. It has the disadvantage that you need to know your architecture, and the kernel is built in the source tree, which is not a good idea. The new kernel build method starts from /usr/src, the same directory as all other build operations, and it builds the kernel in the /usr/obj hierarchy.

You'll need about 250 MB of free space on /usr/obj to build a kernel. If you're really tight on space, you can reduce this value to about 50 MB by omitting the makeoptions DEBUG=-g specification, but if you have problems with the system at some later stage, it will be much more difficult to find what is causing them.

There are a number of alternative commands for building the kernel:

# cd /usr/src
# make kernel KERNCONF=FREEBIE               build and install kernel and klds
# make buildkernel KERNCONF=FREEBIE          build kernel and klds
#make installkernel KERNCONF=FREEBIE         install prebuilt kernel and klds
#make reinstallkernel KERNCONF=FREEBIE       reinstall kernel and klds
# make kernel KERNCONF=FREEBIE -DNO_MODULES  build and install kernel only

The easiest way is make kernel, which is subdivided into the buildkernel and installkernel steps. You can perform these steps individually if you want. If you use the reinstallkernel target instead of the installkernel target, the /boot/kernel.old hierarchy remains unchanged. This is useful when a previous kernel build failed to boot.

If you know the klds are not going to change, you can speed things up by not building them again. Use the -DNO_MODULES flag in combination with any of the other targets to inhibit building or installing the klds, as shown in the last example. Don't do this the first time you build the kernel: if you have mismatches between the kernel and the klds, you may find it impossible to start the system. On the other hand, if you find the kernel doesn't boot, and you want to change the configuration file and rebuild it from the same sources, you can save some time like this.

The first step in building the kernel is to run the config program. You no longer have to do this yourself; the buildkernel and kernel targets do it for you. config creates a directory in which to build the kernel and fills it with the necessary infrastructure, notably the kernel Makefile and a number of header files.

It's possible to get error messages at this stage if you have made a mistake in the config file. If the config command fails when you give it your kernel description, you've probably made a simple error somewhere. Fortunately, config will print the line number that it had trouble with, so you can quickly find it with an editor. For example:

config: line 17: syntax error

One possibility is that you have mistyped a keyword. Compare it to the entry in the GENERIC or LINT kernel definitions.

The next step is to compile all the source files and create a kernel and a set of matching klds. It can take some time, up to an hour on a slow machine. It's also possible to have errors, and unfortunately they are usually not self-explanatory. If the make command fails, it usually signals an error in your kernel description that is not obvious enough for config to catch. A common one is when you omit an entry from the configuration file which is a prerequisite for an entry which is present. For example, if you have SCSI disks (device da), you require the scbus device as well, and if you have just about any kind of Ethernet card, you require the miibus device as well:

device   scbus   # SCSI bus (required)
device   da      # Direct Access (disks)
device   miibus  # MII bus support
device   fxp     # Intel EtherExpress PRO/100B (82557, 82558)

If you leave scbus or miibus out of the configuration, config will not complain, but the kernel link phase will fail with lots of unresolved references.

If you can't resolve the problem after comparing your configuration file with GENERIC, send mail to FreeBSD-questions@FreeBSD.org with your kernel configuration, and it should be diagnosed very quickly. A description of how to interpret these errors has been in the works for a long time, but currently it's still deep magic.

Rebooting

Next, shutdown the system and reboot load the new kernel:

# shutdown -r now

If the new kernel does not boot, or fails to recognize your devices, don't panic. Reset the machine, and when the boot prompt appears, press the space bar to interrupt the boot. Then boot the old kernel:

Ok unload                        remove the kernel that the loader has loaded
Ok load /boot/kernel.old/kernel  load the previous kernel
Ok boot

When reconfiguring a kernel, it is always a good idea to keep on hand a kernel that is known to work. There are two points here:

  • If your kernel doesn't boot, you don't want to save it to kernel.old when you build a new one. It's no use, and if the new kernel doesn't boot either, you'll be left without a runnable kernel. In this case, use the reinstallkernel target mentioned above:
    # make buildkernel KERNCONF=FREEBIE      build kernel and klds
    # make reinstallkernel KERNCONF=FREEBIE  reinstall kernel and klds
    
  • You could still make a mistake and type make install, throwing away your last good kernel. It's easy enough to end up with a completely unbootable system like this. It's a good idea to keep another kernel copy with a name like kernel.save, which the installation procedure does not touch.

After booting with a good kernel you can check over your configuration file and try to build it again. One helpful resource is the /var/log/messages file which records, among other things, all of the kernel messages from every successful boot. Also, the dmesg command prints the most recent kernel messages from the current boot. After some time the original messages are overwritten, so the system startup procedure saves the messages at boot time in the file /var/run/dmesg.boot. Note that most laptops maintain the previous contents of the kernel message buffer when rebooted, so the beginning of the output of dmesg may relate to an earlier boot. Check through to the end before jumping to conclusions.

Making device nodes

FreeBSD Release 5 comes with devfs, the device file system. One great advantage of devfs is that it automatically creates device nodes for the hardware it finds, so you no longer need to run the /dev/MAKEDEV script supplied with older releases of FreeBSD.

Kernel loadable modules

As we saw at the beginning of the chapter, you may not have to build a new kernel to implement the functionality you want. Instead, just load it into the running kernel with a Kernel Loadable Module (kld). The directory /boot/kernel/modules contains a number of klds. To load them, use kldload. For example, if you wanted to load SCO UNIX compatibility, you would enter:

#  kldload ibcs2

This loads the module /boot/kernel/modules/ibcs2.ko. Note that you don't need to specify the directory name, nor the .ko extension.

To find what modules are loaded, use kldstat:

# kldstat
Id Refs  Address      Size    Name
1     5  0xc0100000   1d08b0  kernel
2     2  0xc120d000   a000    ibcs2.ko
3     1  0xc121b000   3000    ibcs2_coff.ko
4     1  0xc1771000   e000    linux.ko
5     1  0xc177f000   bf000   vinum.ko

You can also unload some klds, but not all of them. Use kldunload for this purpose:

#  kldunload vinum

You can't unload a kld which has active resources. In the case of vinum, for example, you can only unload it when none of its volumes are mounted.