Migrating to Linux Kernel 2

Embed Size (px)

Citation preview

  • 8/9/2019 Migrating to Linux Kernel 2

    1/5

    Migrating to Linux kernel 2.6 -- Part 2: Migrating devicedrivers to Linux kernel 2.6

    Overview of Device Drivers and Loadable Kernel Modules

    The kernel is the heart of the Linux operating system, managing all system threads, processes, resources,and resource allocation. Unlike most other operating systems, Linux enables users to reconfigure the kernel,which is usually done to reduce its size and add or deactivate support for specific devices or subsystems.Reconfiguring the kernel to remove support for unused devices and subsystems is quite common whendeveloping embedded systems, because a smaller kernel requires less memory, increasing the resourcesavailable to your applications.

    Device drivers are the software interface between your hardware and the Linux kernel. Device drivers arelow-level, hardware-specific software components that enable devices to interact with more generic, higher-level application programming interfaces (APIs). Providing support for a specific subsystem or hardwareinterface, such as SCSI, USB, or PCMCIA, is very different than providing support for every SCSI, USB, orPCMCIA device. Testing every possible device that could be used over a specific subsystem is animpossibility; new devices are being made available every day. The kernel provides support for specificsubsystems; device drivers provide support for specific devices that use those subsystems. Maintaining theseparation of high-level APIs and low-level device functionality makes it relatively fast and easy to add

    support for new devices to existing systems by writing the appropriate driver for a new device and making itavailable to the kernel.

    Linux device drivers can be integrated into the kernel in two different ways: either by compiling them intothe kernel so that they are always available, or by compiling them into an object format that the kernel canload whenever access to a specific device is required. Kernel code that can be automatically loaded into thekernel is referred to as a loadable kernel module. When configuring the Linux kernel, each kernelconfiguration editor displays a description of available kernel configuration variables and enables you tospecify whether each should be deactivated, compiled into the kernel, or compiled as a loadable kernelmodule.

    Compiling device drivers into the kernel has the advantage that they are always instantly available, but eachincreases the size of the kernel that you are running. Compiling device drivers as loadable kernel modulesimplies some slight overhead when you search for and initially load the module in order to access theassociated device, plus some small runtime overhead, but these are negligible compared to the savings insize and associated memory requirements. Writing device drivers as loadable kernel modules also providessignificant advantages during development. As you develop and debug your device driver, you candynamically unload the previous version and load the new version each time you want to test the newversion. If your device driver is compiled into the kernel, you have to recompile the kernel and reboot eachtime that you want to test a set of iterative changes. Similarly, developing and deploying device drivers asloadable kernel modules simplifies maintaining them in the field, since the device driver can be updated as aseparate system component without requiring a kernel update.

    Configuring your kernel for support for loadable modules is done in the Loadable module support section ofyour kernel configuration editor. The Automatic kernel module loading option determines whether the kernelwill automatically try to locate and load modules as they are needed by new devices or subsystems. TheModule versioning support option (marked as experimental in the current 2.6 kernel source) adds extraversioning information to compiled modules at build-time. This information is designed to help increasemodule portability to kernels other than the one that they were compiled against. The Module unloading

    option is new to 2.6 kernel support for loadable kernel modules. You must enable this option if you wantyour kernel to be able to unload modules when they are no longer needed. This is especially important inresource-constrained and power-sensitive environments such as embedded systems. If you activate thisoption, you can also activate the Forced module unloading option, which enables you to forcibly unloadmodules regardless of whether the kernel believes that they are in use.

    Once you have compiled and installed a loadable kernel module (and you are using a kernel with Automatickernel module loading enabled), the loadable kernel module can be automatically loaded when thecorresponding device is first accessed, provided that the depmod command has been used to create themodule dependency tree. Loadable kernel modules are traditionally installed into a subdirectory of thesystem's /lib/modules directory - the name of this subdirectory is based on the values of the VERSION,

  • 8/9/2019 Migrating to Linux Kernel 2

    2/5

  • 8/9/2019 Migrating to Linux Kernel 2

    3/5

    This macro, introduced in later versions of the 2.4 kernel, defines the module as being licensed under theterms of GPL Version 2 or later. Other valid values are "GPL v2", "GPL and additional rights", "DualBSD/GPL" (your choice of BSD or GPL licensing), "Dual MPL/GPL" (your choice of Mozilla or GPL licensing),and "Proprietary", which is self-explanatory.

    A generic template for a minimal 2.6 device driver would therefore be the following:#include img src="/files/misc/lt.gif">linux/module.h>

    #include img src="/files/misc/lt.gif">linux/config.h>#include img src="/files/misc/lt.gif">linux/init.h>MODULE_LICENSE("GPL");static int __init name_of_initialization_routine(void) {

    /* code goes here */return 0;

    }static void __exit name_of_cleanup_routine(void) {

    /* code goes here */}module_init(name_of_initialization_routine);module_exit(name_of_cleanup_routine);Aside from changes required to device drivers themselves, the most significant change to working withdevice drivers for the 2.6 Linux kernel are the changes in the build process described in the next section.

    Changes to the Build Process for Modules

    One basic change that affects everyone who works on a loadable device driver that is not part of the corekernel source code is the integration of external module compilation into the standard kernel buildmechanism. If you are not using an integrated development environment such as TimeSys' TimeStorm thatis capable of detecting kernel versions and automatically creating Makefiles that "do the right thing" for the2.6 kernel, you will need to manually create Makefiles for your device drivers that are integrated into thekernel build process.

    Under 2.4 and earlier Linux kernels, modules could be developed and compiled anywhere by passingappropriate compilation flags on the command line or in the module's Makefile. These flags consisted of twosymbol definitions required when compiling modules, and a pointer to the directory containing the kernelinclude files, as in the following example that would produce a loadable kernel module named testmod.o:

    gcc -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4.21/include -O2 -c testmod.c

    When building modules for the 2.6 kernel, the process is simpler, but the requirements for successfulcompilation are different. By integrating the process of building external modules into the standard kernelbuild system, you don't have to manually specify module-oriented declarations such as MODULE,__KERNEL__, or newer symbols such as KBUILD_BASENAME and KBUILD_MODNAME. You also do not needto specify options such as -O2 (an optimization option for the gcc C compiler that enables optimizations suchas inlining) - because your module is compiled like any other loadable kernel module, the make processautomatically uses all mandatory flags. Module Makefiles are therefore much simpler, as in the following2.6-compatible Makefile for the module testmod.ko:

    obj-m := testmod.o

    However, in order to build an external module, you must have write access to your kernel source tree in

    order to create temporary directories created and used during compilation. A sample command line forbuilding a module for the 2.6 kernel is the following, which would be executed from within the directorycontaining your module's source code, as always:

    # make -C /usr/src/linux-2.6.1 SUBDIRS=$PWD modules

    This sample command assumes that your module source code and Makefile are located in the directory fromwhich you are excuting the command. If you are not using a POSIX shell such as BASH, you can replace theSUBDIRS argument's use of the $PWD variable with SUBDIRS=`pwd`, which will use the actual pwdcommand to identify the working directory.

  • 8/9/2019 Migrating to Linux Kernel 2

    4/5

  • 8/9/2019 Migrating to Linux Kernel 2

    5/5

    requires changes to how your device drivers identify any device nodes that they use. When using the

    traditional /dev directory as the location of Linux device descriptor files, a device driver registers a device by

    calling either the register_blkdev() or register_chrdev()functions, depending on whether the driver is

    registering a block or character device, and must know its major and minor device numbers "in advance".

    This is the case even if you are using the new udev device mechanism, since udev is primarily a hotplug-

    aware set of scripts that automatically create and delete entries in the /dev directory.

    When using the devfs device filesystem, device drivers must use the the devfs_register() system call to

    register their devices. Drivers can either continue to use pre-assigned major and minor numbers, or they

    can let devfs assign them automatically by specifying the DEVFS_FL_AUTO_DEVNUM flag to the

    devfs_register()call.

    Conclusion

    Changes to the kernel are always motivated by improvements, whether new features, simplification, or

    standardization. Each new Linux kernel introduces many changes that have implications for developers at all

    levels. This white paper provided an overview of 2.6-related changes to device drivers and the build process.

    Tools such as TimeSys TimeStorm that are already 2.6-aware provide updated driver templates and

    automatically create and manage Makefiles for 2.6 loadable kernel modules. However, if you are manually

    maintaining existing device drivers or developing new ones, you will need to incorporate 2.6-related changesinto your manual procedures.

    For general information about writing device drivers, "Linux Device Drivers, 2nd Edition" by Alessandro

    Rubini and Jonathan Corbet (ISBN 0596000081) is an excellent book on developing, debugging, and using

    Linux device drivers. The version of this book associated with the 2.4 kernel is available online at the URL

    http://www.xml.com/ldd/chapter/book/. A new version of this book is in progress to discuss 2.6 issues. Until

    a new edition is available, Mr. Corbet has written an excellent series of articles on writing device drivers for

    the 2.6 kernel. These are available at the Linux Weekly News. Similarly, the documentation provided with

    TimeSys' Linux Development Suite (LDS) provides detailed examples of writing device drivers, focusing on

    high-performance drivers for embedded use.

    http://lwn.net/Articles/driver-porting/http://lwn.net/Articles/driver-porting/