This is, on the surface, a book about writing device drivers for the Linux system.That is a worthy goal, of course; the flow of new hardware products is not likely toslow down anytime so
Trang 1DEVICE DRIVERS
Trang 2Other Linux resources from O’Reilly
Related titles Understanding the Linux
KernelLinux in a NutshellRunning LinuxLinux NetworkAdministrator’s Guide
Linux Pocket GuideBuilding Embedded LinuxSystems
Designing EmbeddedHardware
Linux Books Resource Center
linux.oreilly.com is a complete catalog of O’Reilly’s books on
Linux and Unix and related technologies, including samplechapters and code examples
ONLamp.com is the premier site for the open source web
plat-form: Linux, Apache, MySQL, and either Perl, Python, or PHP
Conferences O’Reilly brings diverse innovators together to nurture the ideas
that spark revolutionary industries We specialize in ing the latest tools and systems, translating the innovator’s
document-knowledge into useful skills for those in the trenches Visit ferences.oreilly.com for our upcoming events.
con-Safari Bookshelf (safari.oreilly.com) is the premier online
refer-ence library for programmers and IT professionals Conductsearches across more than 1,000 books Subscribers can zero in
on answers to time-critical questions in a matter of seconds.Read the books on your Bookshelf from cover to cover or sim-ply flip to the page you need Try it today with a free trial
Trang 3DEVICE DRIVERS
THIRD EDITION
Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
Trang 4Linux Device Drivers, Third Edition
by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
Copyright © 2005, 2001, 1998 O’Reilly Media, Inc All rights reserved.
Printed in the United States of America.
Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472 O’Reilly books may be purchased for educational, business, or sales promotional use Online editions
are also available for most titles (safari.oreilly.com) For more information, contact our tutional sales department: (800) 998-9938 or corporate@oreilly.com.
Production Editor: Matt Hutchinson
Production Services: Octal Publishing, Inc.
Interior Designer: Melanie Wang
Printing History:
February 1998: First Edition.
June 2001: Second Edition.
February 2005: Third Edition.
Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of
O’Reilly Media, Inc The Linux series designations, Linux Device Drivers, images of the American West,
and related trade dress are trademarks of O’Reilly Media, Inc.
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks Where those designations appear in this book, and O’Reilly Media, Inc was aware of a trademark claim, the designations have been printed in caps or initial caps.
While every precaution has been taken in the preparation of this book, the publisher and authors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.0
License To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.0/ or send a
letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
This book uses RepKover ™ , a durable and flexible lay-flat binding.
ISBN: 0-596-00590-3
Trang 5Table of Contents
Preface xi
1 An Introduction to Device Drivers 1
2 Building and Running Modules 15
Trang 6Char Device Registration 55
5 Concurrency and Race Conditions 106
7 Time, Delays, and Deferred Work 183
Trang 79 Communicating with Hardware 235
10 Interrupt Handling 258
11 Data Types in the Kernel 288
Trang 814 The Linux Device Model 362
15 Memory Mapping and DMA 412
Trang 917 Network Drivers 497
Bibliography 575 Index 579
Trang 11This is, on the surface, a book about writing device drivers for the Linux system.That is a worthy goal, of course; the flow of new hardware products is not likely toslow down anytime soon, and somebody is going to have to make all those new gad-gets work with Linux But this book is also about how the Linux kernel works andhow to adapt its workings to your needs or interests Linux is an open system; withthis book, we hope, it is more open and accessible to a larger community of developers
This is the third edition of Linux Device Drivers The kernel has changed greatly
since this book was first published, and we have tried to evolve the text to match.This edition covers the 2.6.10 kernel as completely as we are able We have, this timearound, elected to omit the discussion of backward compatibility with previous ker-nel versions The changes from 2.4 are simply too large, and the 2.4 interfaceremains well documented in the (freely available) second edition
This edition contains quite a bit of new material relevant to the 2.6 kernel The cussion of locking and concurrency has been expanded and moved into its ownchapter The Linux device model, which is new in 2.6, is covered in detail There arenew chapters on the USB bus and the serial driver subsystem; the chapter on PCI hasalso been enhanced While the organization of the rest of the book resembles that ofthe earlier editions, every chapter has been thoroughly updated
dis-We hope you enjoy reading this book as much as we have enjoyed writing it
Jon’s Introduction
The publication of this edition coincides with my twelth year of working with Linuxand, shockingly, my twenty-fifth year in the computing field Computing seemed like
a fast-moving field back in 1980, but things have sped up a lot since then Keeping
Linux Device Drivers up to date is increasingly a challenge; the Linux kernel hackers
continue to improve their code, and they have little patience for documentation thatfails to keep up
Trang 12Linux continues to succeed in the market and, more importantly, in the hearts andminds of developers worldwide The success of Linux is clearly a testament to itstechnical quality and to the numerous benefits of free software in general But thetrue key to its success, in my opinion, lies in the fact that it has brought the fun back
to computing With Linux, anybody can get their hands into the system and play in asandbox where contributions from any direction are welcome, but where technicalexcellence is valued above all else Linux not only provides us with a top-qualityoperating system; it gives us the opportunity to be part of its future development and
to have fun while we’re at it
In my 25 years in the field, I have had many interesting opportunities, from ming the first Cray computers (in Fortran, on punch cards) to seeing the minicom-puter and Unix workstation waves, through to the current, microprocessor-dominated era Never, though, have I seen the field more full of life, opportunity,and fun Never have we had such control over our own tools and their evolution.Linux, and free software in general, is clearly the driving force behind those changes
program-My hope is that this edition helps to bring that fun and opportunity to a new set ofLinux developers Whether your interests are in the kernel or in user space, I hopeyou find this book to be a useful and interesting guide to just how the kernel workswith the hardware I hope it helps and inspires you to fire up your editor and tomake our shared, free operating system even better Linux has come a long way, but
it is also just beginning; it will be more than interesting to watch—and participatein—what happens from here
Alessandro’s Introduction
I’ve always enjoyed computers because they can talk to external hardware So, aftersoldering my devices for the Apple II and the ZX Spectrum, backed with the Unixand free software expertise the university gave me, I could escape the DOS trap byinstalling GNU/Linux on a fresh new 386 and by turning on the soldering iron onceagain
Back then, the community was a small one, and there wasn’t much documentationabout writing drivers around, so I started writing for Linux Journal That’s howthings started: when I later discovered I didn’t like writing papers, I left the univer-isty and found myself with an O’Reilly contract in my hands
That was in 1996 Ages ago
The computing world is different now: free software looks like a viable solution,both technically and politically, but there’s a lot of work to do in both realms I hopethis book furthers two aims: spreading technical knowledge and raising awarenessabout the need to spread knowledge That’s why, after the first edition proved inter-esting to the public, the two authors of the second edition switched to a free license,
Trang 13supported by our editor and our publisher I’m betting this is the right approach toinformation, and it’s great to team up with other people sharing this vision.
I’m excited by what I witness in the embedded arena, and I hope this text helps bydoing more; but ideas are moving fast these days, and it’s already time to plan for thefourth edition, and look for a fourth author to help
sys-it could possibly be
I am honored that I’ve had the ability to contribute to this book I hope that itenables others to learn the details about the kernel, discover that driver development
is not a scary or forbidding place, and possibly encourage others to join in and help
in the collective effort of making this operating system work on every computingplatform with every type of device available The development procedure is fun, thecommunity is rewarding, and everyone benefits from the effort involved
Now it’s back to making this edition obsolete by fixing current bugs, changing APIs
to work better and be simpler to understand for everyone, and adding new features.Come along; we can always use the help
Audience for This Book
This book should be an interesting source of information both for people who want
to experiment with their computer and for technical programmers who face the need
to deal with the inner levels of a Linux box Note that “a Linux box” is a wider cept than “a PC running Linux,” as many platforms are supported by our operatingsystem, and kernel programming is by no means bound to a specific platform Wehope this book is useful as a starting point for people who want to become kernelhackers but don’t know where to start
con-On the technical side, this text should offer a hands-on approach to understandingthe kernel internals and some of the design choices made by the Linux developers.Although the main, official target of the book is teaching how to write device drivers,the material should give an interesting overview of the kernel implementation as well
Trang 14Although real hackers can find all the necessary information in the official kernelsources, usually a written text can be helpful in developing programming skills Thetext you are approaching is the result of hours of patient grepping through the ker-nel sources, and we hope the final result is worth the effort it took.
The Linux enthusiast should find in this book enough food for her mind to startplaying with the code base and should be able to join the group of developers that iscontinuously working on new capabilities and performance enhancements Thisbook does not cover the Linux kernel in its entirety, of course, but Linux devicedriver authors need to know how to work with many of the kernel’s subsystems.Therefore, it makes a good introduction to kernel programming in general Linux isstill a work in progress, and there’s always a place for new programmers to jump intothe game
If, on the other hand, you are just trying to write a device driver for your own device,and you don’t want to muck with the kernel internals, the text should be modular-ized enough to fit your needs as well If you don’t want to go deep into the details,you can just skip the most technical sections, and stick to the standard API used bydevice drivers to seamlessly integrate with the rest of the kernel
Organization of the Material
The book introduces its topics in ascending order of complexity and is divided intotwo parts The first part (Chapters 1–11) begins with the proper setup of kernel mod-ules and goes on to describe the various aspects of programming that you’ll need inorder to write a full-featured driver for a char-oriented device Every chapter covers adistinct problem and includes a quick summary at the end, which can be used as areference during actual development
Throughout the first part of the book, the organization of the material moves roughlyfrom the software-oriented concepts to the hardware-related ones This organization
is meant to allow you to test the software on your own computer as far as possiblewithout the need to plug external hardware into the machine Every chapter includessource code and points to sample drivers that you can run on any Linux computer
In Chapters 1 and 1, however, we ask you to connect an inch of wire to the parallelport in order to test out hardware handling, but this requirement should be manage-able by everyone
The second half of the book (Chapters 12–18) describes block drivers and networkinterfaces and goes deeper into more advanced topics, such as working with the vir-tual memory subsystem and with the PCI and USB buses Many driver authors donot need all of this material, but we encourage you to go on reading anyway Much
of the material found there is interesting as a view into how the Linux kernel works,even if you do not need it for a specific project
Trang 15Background Information
In order to be able to use this book, you need to be confident with C programming.Some Unix expertise is needed as well, as we often refer to Unix semantics about sys-tem calls, commands, and pipelines
At the hardware level, no previous expertise is required to understand the material inthis book, as long as the general concepts are clear in advance The text isn’t based
on specific PC hardware, and we provide all the needed information when we dorefer to specific hardware
Several free software tools are needed to build the kernel, and you often need cific versions of these tools Those that are too old can lack needed features, whilethose that are too new can occasionally generate broken kernels Usually, the toolsprovided with any current distribution work just fine Tool version requirements
spe-vary from one kernel to the next; consult Documentation/Changes in the source tree
of the kernel you are using for exact requirements
Online Version and License
The authors have chosen to make this book freely available under the Creative mons “Attribution-ShareAlike” license, Version 2.0:
Com-http://www.oreilly.com/catalog/linuxdrive3
Conventions Used in This Book
The following is a list of the typographical conventions used in this book:
Constant Width Italic
Used to indicate text within commands that the user replaces with an actualvalue
Constant Width Bold
Used in examples to show commands or other text that should be typed literally
by the user
Trang 16Pay special attention to notes set apart from the text with the following icons:
This is a tip It contains useful supplementary information about the topic at hand.
This is a warning It helps you solve and avoid annoying problems.
Using Code Examples
This book is here to help you get your job done In general, you may use the code inthis book in your programs and documentation The code samples are covered by adual BSD/GPL license
We appreciate, but do not require, attribution An attribution usually includes the
title, author, publisher, and ISBN For example: “Linux Device Drivers, Third
Edi-tion, by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman Copyright
2005 O’Reilly Media, Inc., 0-596-00590-3.”
We’d Like to Hear from You
Please address comments and questions concerning this book to the publisher:O’Reilly Media, Inc
1005 Gravenstein Highway North
Trang 17Safari Enabled
When you see a Safari® Enabled icon on the cover of your favorite nology book, that means the book is available online through theO’Reilly Network Safari Bookshelf
tech-Safari offers a solution that’s better than e-books It’s a virtual library that lets youeasily search thousands of top tech books, cut and paste code samples, downloadchapters, and find quick answers when you need the most accurate, current informa-
tion Try it for free at http://safari.oreilly.com.
The first edition was technically reviewed by Alan Cox, Greg Hankins, Hans men, Heiko Eissfeldt, and Miguel de Icaza (in alphabetic order by first name) Thetechnical reviewers for the second edition were Allan B Cruse, Christian Morgner,Jake Edge, Jeff Garzik, Jens Axboe, Jerry Cooperstein, Jerome Peter Lynch, MichaelKerrisk, Paul Kinzelman, and Raph Levien Reviewers for the third edition wereAllan B Cruse, Christian Morgner, James Bottomley, Jerry Cooperstein, PatrickMochel, Paul Kinzelman, and Robert Love Together, these people have put a vastamount of effort into finding problems and pointing out possible improvements toour writing
Ler-Last but certainly not least, we thank the Linux developers for their relentless work.This includes both the kernel programmers and the user-space people, who often getforgotten In this book, we chose never to call them by name in order to avoid beingunfair to someone we might forget We sometimes made an exception to this ruleand called Linus by name; we hope he doesn’t mind
Jon
I must begin by thanking my wife Laura and my children Michele and Giulia for ing my life with joy and patiently putting up with my distraction while working onthis edition The subscribers of LWN.net have, through their generosity, enabledmuch of this work to happen The Linux kernel developers have done me a great ser-vice by letting me be a part of their community, answering my questions, and setting
fill-me straight when I got confused Thanks are due to readers of the second edition ofthis book whose comments, offered at Linux gatherings over much of the world,
Trang 18have been gratifying and inspiring And I would especially like to thank AlessandroRubini for starting this whole exercise with the first edition (and staying with itthrough the current edition); and Greg Kroah-Hartman, who has brought his consid-erable skills to bear on several chapters, with great results.
Alessandro
I would like to thank the people that made this work possible First of all, the ible patience of Federica, who went as far as letting me review the first edition dur-ing our honeymoon, with a laptop in the tent I want to thank Giorgio and Giulia,who have been involved in later editions of the book and happily accepted to be sons
incred-of “a gnu” who incred-often works late in the night I owe a lot to all the free-sincred-oftwareauthors who actually taught me how to program by making their work available foranyone to study But for this edition, I’m mostly grateful to Jon and Greg, who havebeen great mates in this work; it couldn’t have existed without each and both ofthem, as the code base is bigger and tougher, while my time is a scarcer resource,always contended for by clients, free software issues, and expired deadlines Jon hasbeen a great leader for this edition; both have been very productive and technicallyinvaluable in supplementing my small-scale and embedded view toward program-ming with their expertise about SMP and number crunchers
Greg
I would like to thank my wife Shannon and my children Madeline and Griffin fortheir understanding and patience while I took the time to work on this book If itwere not for their support of my original Linux development efforts, I would not beable to do this book at all Thanks also to Alessandro and Jon for offering to let mework on this book; I am honored that they let me participate in it Much gratitude isgiven to all of the Linux kernel programmers, who were unselfish enough to writecode in the public view, so that I and others could learn so much from just reading it.Also, for everyone who has ever sent me bug reports, critiqued my code, and flamed
me for doing stupid things, you have all taught me so much about how to be a betterprogrammer and, throughout it all, made me feel very welcome to be part of thiscommunity Thank you
Trang 19Device drivers take on a special role in the Linux kernel They are distinct “blackboxes” that make a particular piece of hardware respond to a well-defined internalprogramming interface; they hide completely the details of how the device works.User activities are performed by means of a set of standardized calls that are indepen-dent of the specific driver; mapping those calls to device-specific operations that act
on real hardware is then the role of the device driver This programming interface issuch that drivers can be built separately from the rest of the kernel and “plugged in”
at runtime when needed This modularity makes Linux drivers easy to write, to thepoint that there are now hundreds of them available
There are a number of reasons to be interested in the writing of Linux device drivers.The rate at which new hardware becomes available (and obsolete!) alone guaranteesthat driver writers will be busy for the foreseeable future Individuals may need toknow about drivers in order to gain access to a particular device that is of interest tothem Hardware vendors, by making a Linux driver available for their products, canadd the large and growing Linux user base to their potential markets And the opensource nature of the Linux system means that if the driver writer wishes, the source
to a driver can be quickly disseminated to millions of users
This book teaches you how to write your own drivers and how to hack around inrelated parts of the kernel We have taken a device-independent approach; the pro-gramming techniques and interfaces are presented, whenever possible, without beingtied to any specific device Each driver is different; as a driver writer, you need to
Trang 20understand your specific device well But most of the principles and basic niques are the same for all drivers This book cannot teach you about your device,but it gives you a handle on the background you need to make your device work.
tech-As you learn to write drivers, you find out a lot about the Linux kernel in general;this may help you understand how your machine works and why things aren’talways as fast as you expect or don’t do quite what you want We introduce newideas gradually, starting off with very simple drivers and building on them; every newconcept is accompanied by sample code that doesn’t need special hardware to betested
This chapter doesn’t actually get into writing code However, we introduce somebackground concepts about the Linux kernel that you’ll be glad you know later,when we do launch into programming
The Role of the Device Driver
As a programmer, you are able to make your own choices about your driver, andchoose an acceptable trade-off between the programming time required and the flexi-bility of the result Though it may appear strange to say that a driver is “flexible,” welike this word because it emphasizes that the role of a device driver is providing
mechanism, not policy.
The distinction between mechanism and policy is one of the best ideas behind theUnix design Most programming problems can indeed be split into two parts: “whatcapabilities are to be provided” (the mechanism) and “how those capabilities can beused” (the policy) If the two issues are addressed by different parts of the program,
or even by different programs altogether, the software package is much easier todevelop and to adapt to particular needs
For example, Unix management of the graphic display is split between the X server,which knows the hardware and offers a unified interface to user programs, and thewindow and session managers, which implement a particular policy without know-ing anything about the hardware People can use the same window manager on dif-ferent hardware, and different users can run different configurations on the sameworkstation Even completely different desktop environments, such as KDE andGNOME, can coexist on the same system Another example is the layered structure
of TCP/IP networking: the operating system offers the socket abstraction, whichimplements no policy regarding the data to be transferred, while different servers are
in charge of the services (and their associated policies) Moreover, a server like ftpd
provides the file transfer mechanism, while users can use whatever client they prefer;both command-line and graphic clients exist, and anyone can write a new user inter-face to transfer files
Where drivers are concerned, the same separation of mechanism and policy applies.The floppy driver is policy free—its role is only to show the diskette as a continuous
Trang 21array of data blocks Higher levels of the system provide policies, such as who mayaccess the floppy drive, whether the drive is accessed directly or via a filesystem, andwhether users may mount filesystems on the drive Since different environments usu-ally need to use hardware in different ways, it’s important to be as policy free aspossible.
When writing drivers, a programmer should pay particular attention to this mental concept: write kernel code to access the hardware, but don’t force particularpolicies on the user, since different users have different needs The driver should deal
funda-with making the hardware available, leaving all the issues about how to use the
hard-ware to the applications A driver, then, is flexible if it offers access to the hardhard-warecapabilities without adding constraints Sometimes, however, some policy decisionsmust be made For example, a digital I/O driver may only offer byte-wide access tothe hardware in order to avoid the extra code needed to handle individual bits.You can also look at your driver from a different perspective: it is a software layerthat lies between the applications and the actual device This privileged role of thedriver allows the driver programmer to choose exactly how the device should appear:different drivers can offer different capabilities, even for the same device The actualdriver design should be a balance between many different considerations Forinstance, a single device may be used concurrently by different programs, and thedriver programmer has complete freedom to determine how to handle concurrency.You could implement memory mapping on the device independently of its hardwarecapabilities, or you could provide a user library to help application programmersimplement new policies on top of the available primitives, and so forth One majorconsideration is the trade-off between the desire to present the user with as manyoptions as possible and the time you have to write the driver, as well as the need tokeep things simple so that errors don’t creep in
Policy-free drivers have a number of typical characteristics These include support forboth synchronous and asynchronous operation, the ability to be opened multipletimes, the ability to exploit the full capabilities of the hardware, and the lack of soft-ware layers to “simplify things” or provide policy-related operations Drivers of thissort not only work better for their end users, but also turn out to be easier to writeand maintain as well Being policy-free is actually a common target for softwaredesigners
Many device drivers, indeed, are released together with user programs to help withconfiguration and access to the target device Those programs can range from simple
utilities to complete graphical applications Examples include the tunelp program, which adjusts how the parallel port printer driver operates, and the graphical cardctl
utility that is part of the PCMCIA driver package Often a client library is provided aswell, which provides capabilities that do not need to be implemented as part of thedriver itself
Trang 22The scope of this book is the kernel, so we try not to deal with policy issues or withapplication programs or support libraries Sometimes we talk about different poli-cies and how to support them, but we won’t go into much detail about programsusing the device or the policies they enforce You should understand, however, thatuser programs are an integral part of a software package and that even policy-freepackages are distributed with configuration files that apply a default behavior to theunderlying mechanisms.
Splitting the Kernel
In a Unix system, several concurrent processes attend to different tasks Each process
asks for system resources, be it computing power, memory, network connectivity, or
some other resource The kernel is the big chunk of executable code in charge of
han-dling all such requests Although the distinction between the different kernel tasksisn’t always clearly marked, the kernel’s role can be split (as shown in Figure 1-1)into the following parts:
Process management
The kernel is in charge of creating and destroying processes and handling theirconnection to the outside world (input and output) Communication among dif-ferent processes (through signals, pipes, or interprocess communication primi-tives) is basic to the overall system functionality and is also handled by thekernel In addition, the scheduler, which controls how processes share the CPU,
is part of process management More generally, the kernel’s process ment activity implements the abstraction of several processes on top of a singleCPU or a few of them
manage-Memory management
The computer’s memory is a major resource, and the policy used to deal with it
is a critical one for system performance The kernel builds up a virtual ing space for any and all processes on top of the limited available resources Thedifferent parts of the kernel interact with the memory-management subsystem
address-through a set of function calls, ranging from the simple malloc/free pair to much
more complex functionalities
Filesystems
Unix is heavily based on the filesystem concept; almost everything in Unix can
be treated as a file The kernel builds a structured filesystem on top of tured hardware, and the resulting file abstraction is heavily used throughout thewhole system In addition, Linux supports multiple filesystem types, that is, dif-ferent ways of organizing data on the physical medium For example, disks may
unstruc-be formatted with the Linux-standard ext3 filesystem, the commonly used FATfilesystem or several others
Trang 23Device control
Almost every system operation eventually maps to a physical device With theexception of the processor, memory, and a very few other entities, any and alldevice control operations are performed by code that is specific to the device
being addressed That code is called a device driver The kernel must have
embedded in it a device driver for every peripheral present on a system, from thehard drive to the keyboard and the tape drive This aspect of the kernel’s func-tions is our primary interest in this book
Networking
Networking must be managed by the operating system, because most networkoperations are not specific to a process: incoming packets are asynchronousevents The packets must be collected, identified, and dispatched before a pro-cess takes care of them The system is in charge of delivering data packets acrossprogram and network interfaces, and it must control the execution of programsaccording to their network activity Additionally, all the routing and address res-olution issues are implemented within the kernel
Loadable Modules
One of the good features of Linux is the ability to extend at runtime the set of tures offered by the kernel This means that you can add functionality to the kernel(and remove functionality as well) while the system is up and running
fea-Each piece of code that can be added to the kernel at runtime is called a module The
Linux kernel offers support for quite a few different types (or classes) of modules,including, but not limited to, device drivers Each module is made up of object code(not linked into a complete executable) that can be dynamically linked to the run-
ning kernel by the insmod program and can be unlinked by the rmmod program.
Figure 1-1 identifies different classes of modules in charge of specific tasks—a ule is said to belong to a specific class according to the functionality it offers Theplacement of modules in Figure 1-1 covers the most important classes, but is far fromcomplete because more and more functionality in Linux is being modularized
mod-Classes of Devices and Modules
The Linux way of looking at devices distinguishes between three fundamental devicetypes Each module usually implements one of these types, and thus is classifiable as a
char module, a block module, or a network module This division of modules into
dif-ferent types, or classes, is not a rigid one; the programmer can choose to build hugemodules implementing different drivers in a single chunk of code Good program-mers, nonetheless, usually create a different module for each new functionality theyimplement, because decomposition is a key element of scalability and extendability
Trang 24The three classes are:
of char devices, as they are well represented by the stream abstraction Char
devices are accessed by means of filesystem nodes, such as /dev/tty1 and /dev/lp0.
The only relevant difference between a char device and a regular file is that youcan always move back and forth in the regular file, whereas most char devicesare just data channels, which you can only access sequentially There exist,nonetheless, char devices that look like data areas, and you can move back andforth in them; for instance, this usually applies to frame grabbers, where the
applications can access the whole acquired image using mmap or lseek.
Figure 1-1 A split view of the kernel
features implemented as modules
Process management management Memory Filesystems control Device Networking
dependent code
Arch-Memory manager
Character devices
Network subsystem
Concurrency, multitasking memory Virtual Files and dirs: the VFS
Kernel subsystems
Features implemented
Software support
Hardware
IF drivers Block devices
File system types
Ttys &
device access Connectivity
Disks & CDs Consoles,
etc interfaces Network
The System Call Interface
Trang 25Block devices
Like char devices, block devices are accessed by filesystem nodes in the /dev
directory A block device is a device (e.g., a disk) that can host a filesystem Inmost Unix systems, a block device can only handle I/O operations that transferone or more whole blocks, which are usually 512 bytes (or a larger power oftwo) bytes in length Linux, instead, allows the application to read and write ablock device like a char device—it permits the transfer of any number of bytes at
a time As a result, block and char devices differ only in the way data is managedinternally by the kernel, and thus in the kernel/driver software interface Like achar device, each block device is accessed through a filesystem node, and the dif-ference between them is transparent to the user Block drivers have a completelydifferent interface to the kernel than char drivers
Network interfaces
Any network transaction is made through an interface, that is, a device that is
able to exchange data with other hosts Usually, an interface is a hardware
device, but it might also be a pure software device, like the loopback interface Anetwork interface is in charge of sending and receiving data packets, driven bythe network subsystem of the kernel, without knowing how individual transac-tions map to the actual packets being transmitted Many network connections(especially those using TCP) are stream-oriented, but network devices are, usu-ally, designed around the transmission and receipt of packets A network driverknows nothing about individual connections; it only handles packets
Not being a stream-oriented device, a network interface isn’t easily mapped to a
node in the filesystem, as /dev/tty1 is The Unix way to provide access to
inter-faces is still by assigning a unique name to them (such aseth0), but that namedoesn’t have a corresponding entry in the filesystem Communication betweenthe kernel and a network device driver is completely different from that used
with char and block drivers Instead of read and write, the kernel calls functions
related to packet transmission
There are other ways of classifying driver modules that are orthogonal to the abovedevice types In general, some types of drivers work with additional layers of kernelsupport functions for a given type of device For example, one can talk of universalserial bus (USB) modules, serial modules, SCSI modules, and so on Every USBdevice is driven by a USB module that works with the USB subsystem, but the deviceitself shows up in the system as a char device (a USB serial port, say), a block device(a USB memory card reader), or a network device (a USB Ethernet interface)
Other classes of device drivers have been added to the kernel in recent times, ing FireWire drivers and I2O drivers In the same way that they handled USB andSCSI drivers, kernel developers collected class-wide features and exported them todriver implementers to avoid duplicating work and bugs, thus simplifying andstrengthening the process of writing such drivers
Trang 26includ-In addition to device drivers, other functionalities, both hardware and software, aremodularized in the kernel One common example is filesystems A filesystem typedetermines how information is organized on a block device in order to represent atree of directories and files Such an entity is not a device driver, in that there’s noexplicit device associated with the way the information is laid down; the filesystemtype is instead a software driver, because it maps the low-level data structures tohigh-level data structures It is the filesystem that determines how long a filenamecan be and what information about each file is stored in a directory entry The file-system module must implement the lowest level of the system calls that access direc-tories and files, by mapping filenames and paths (as well as other information, such
as access modes) to data structures stored in data blocks Such an interface is pletely independent of the actual data transfer to and from the disk (or othermedium), which is accomplished by a block device driver
com-If you think of how strongly a Unix system depends on the underlying filesystem,you’ll realize that such a software concept is vital to system operation The ability todecode filesystem information stays at the lowest level of the kernel hierarchy and is
of utmost importance; even if you write a block driver for your new CD-ROM, it is
useless if you are not able to run ls or cp on the data it hosts Linux supports the
con-cept of a filesystem module, whose software interface declares the different tions that can be performed on a filesystem inode, directory, file, and superblock It’squite unusual for a programmer to actually need to write a filesystem module,because the official kernel already includes code for the most important filesystemtypes
opera-Security Issues
Security is an increasingly important concern in modern times We will discuss rity-related issues as they come up throughout the book There are a few general con-cepts, however, that are worth mentioning now
Any security check in the system is enforced by kernel code If the kernel has rity holes, then the system as a whole has holes In the official kernel distribution,
secu-only an authorized user can load modules; the system call init_module checks if the
invoking process is authorized to load a module into the kernel Thus, when ning an official kernel, only the superuser,* or an intruder who has succeeded inbecoming privileged, can exploit the power of privileged code
run-When possible, driver writers should avoid encoding security policy in their code.Security is a policy issue that is often best handled at higher levels within the kernel,under the control of the system administrator There are always exceptions, however
* Technically, only somebody with the CAP_SYS_MODULE capability can perform this operation We discuss capabilities in Chapter 6.
Trang 27As a device driver writer, you should be aware of situations in which some types ofdevice access could adversely affect the system as a whole and should provide ade-quate controls For example, device operations that affect global resources (such assetting an interrupt line), which could damage the hardware (loading firmware, forexample), or that could affect other users (such as setting a default block size on atape drive), are usually only available to sufficiently privileged users, and this checkmust be made in the driver itself.
Driver writers must also be careful, of course, to avoid introducing security bugs.The C programming language makes it easy to make several types of errors Many
current security problems are created, for example, by buffer overrun errors, in which
the programmer forgets to check how much data is written to a buffer, and data ends
up written beyond the end of the buffer, thus overwriting unrelated data Such errorscan compromise the entire system and must be avoided Fortunately, avoiding theseerrors is usually relatively easy in the device driver context, in which the interface tothe user is narrowly defined and highly controlled
Some other general security ideas are worth keeping in mind Any input receivedfrom user processes should be treated with great suspicion; never trust it unless youcan verify it Be careful with uninitialized memory; any memory obtained from thekernel should be zeroed or otherwise initialized before being made available to a userprocess or device Otherwise, information leakage (disclosure of data, passwords,etc.) could result If your device interprets data sent to it, be sure the user cannotsend anything that could compromise the system Finally, think about the possibleeffect of device operations; if there are specific operations (e.g., reloading the firm-ware on an adapter board or formatting a disk) that could affect the system, thoseoperations should almost certainly be restricted to privileged users
Be careful, also, when receiving software from third parties, especially when the nel is concerned: because everybody has access to the source code, everybody canbreak and recompile things Although you can usually trust precompiled kernelsfound in your distribution, you should avoid running kernels compiled by anuntrusted friend—if you wouldn’t run a precompiled binary as root, then you’d bet-ter not run a precompiled kernel For example, a maliciously modified kernel could
ker-allow anyone to load a module, thus opening an unexpected back door via init_module.
Note that the Linux kernel can be compiled to have no module support whatsoever,thus closing any module-related security holes In this case, of course, all neededdrivers must be built directly into the kernel itself It is also possible, with 2.2 andlater kernels, to disable the loading of kernel modules after system boot via the capa-bility mechanism
Trang 28Version Numbering
Before digging into programming, we should comment on the version numberingscheme used in Linux and which versions are covered by this book
First of all, note that every software package used in a Linux system has its own
release number, and there are often interdependencies across them: you need a ticular version of one package to run a particular version of another package Thecreators of Linux distributions usually handle the messy problem of matching pack-ages, and the user who installs from a prepackaged distribution doesn’t need to dealwith version numbers Those who replace and upgrade system software, on the otherhand, are on their own in this regard Fortunately, almost all modern distributionssupport the upgrade of single packages by checking interpackage dependencies; thedistribution’s package manager generally does not allow an upgrade until the depen-dencies are satisfied
par-To run the examples we introduce during the discussion, you won’t need particularversions of any tool beyond what the 2.6 kernel requires; any recent Linux distribu-tion can be used to run our examples We won’t detail specific requirements,
because the file Documentation/Changes in your kernel sources is the best source of
such information if you experience any problems
As far as the kernel is concerned, the even-numbered kernel versions (i.e., 2.6.x) are
the stable ones that are intended for general distribution The odd versions (such as
2.7.x), on the contrary, are development snapshots and are quite ephemeral; the
lat-est of them represents the current status of development, but becomes obsolete in afew days or so
This book covers Version 2.6 of the kernel Our focus has been to show all the tures available to device driver writers in 2.6.10, the current version at the time weare writing This edition of the book does not cover prior versions of the kernel Forthose of you who are interested, the second edition covered Versions 2.0 through 2.4
fea-in detail That edition is still available onlfea-ine at http://lwn.net/Kernel/LDD2/.
Kernel programmers should be aware that the development process changed with 2.6.The 2.6 series is now accepting changes that previously would have been consideredtoo large for a “stable” kernel Among other things, that means that internal kernelprogramming interfaces can change, thus potentially obsoleting parts of this book;for this reason, the sample code accompanying the text is known to work with 2.6.10,but some modules don’t compile under earlier versions Programmers wanting tokeep up with kernel programming changes are encouraged to join the mailing listsand to make use of the web sites listed in the bibliography There is also a web page
maintained at http://lwn.net/Articles/2.6-kernel-api/, which contains information
about API changes that have happened since this book was published
Trang 29This text doesn’t talk specifically about odd-numbered kernel versions General usersnever have a reason to run development kernels Developers experimenting with newfeatures, however, want to be running the latest development release They usuallykeep upgrading to the most recent version to pick up bug fixes and new implementa-tions of features Note, however, that there’s no guarantee on experimental kernels,*
and nobody helps you if you have problems due to a bug in a noncurrent bered kernel Those who run odd-numbered versions of the kernel are usually skilledenough to dig in the code without the need for a textbook, which is another reasonwhy we don’t talk about development kernels here
odd-num-Another feature of Linux is that it is a platform-independent operating system, notjust “a Unix clone for PC clones” anymore: it currently supports some 20 architec-tures This book is platform independent as far as possible, and all the code sampleshave been tested on at least the x86 and x86-64 platforms Because the code has beentested on both 32-bit and 64-bit processors, it should compile and run on all otherplatforms As you might expect, the code samples that rely on particular hardwaredon’t work on all the supported platforms, but this is always stated in the sourcecode
License Terms
Linux is licensed under Version 2 of the GNU General Public License (GPL), a ment devised for the GNU project by the Free Software Foundation The GPL allowsanybody to redistribute, and even sell, a product covered by the GPL, as long as therecipient has access to the source and is able to exercise the same rights Addition-ally, any software product derived from a product covered by the GPL must, if it isredistributed at all, be released under the GPL
docu-The main goal of such a license is to allow the growth of knowledge by permittingeverybody to modify programs at will; at the same time, people selling software tothe public can still do their job Despite this simple objective, there’s a never-endingdiscussion about the GPL and its use If you want to read the license, you can find it
in several places in your system, including the top directory of your kernel source
tree in the COPYING file.
Vendors often ask whether they can distribute kernel modules in binary form only.The answer to that question has been deliberately left ambiguous Distribution ofbinary modules—as long as they adhere to the published kernel interface—has beentolerated so far But the copyrights on the kernel are held by many developers, andnot all of them agree that kernel modules are not derived products If you or youremployer wish to distribute kernel modules under a nonfree license, you really need
* Note that there’s no guarantee on even-numbered kernels as well, unless you rely on a commercial provider that grants its own warranty.
Trang 30to discuss the situation with your legal counsel Please note also that the kerneldevelopers have no qualms against breaking binary modules between kernel releases,even in the middle of a stable kernel series If it is at all possible, both you and yourusers are better off if you release your module as free software.
If you want your code to go into the mainline kernel, or if your code requires patches
to the kernel, you must use a GPL-compatible license as soon as you release the code.
Although personal use of your changes doesn’t force the GPL on you, if you ute your code, you must include the source code in the distribution—people acquir-ing your package must be allowed to rebuild the binary at will
distrib-As far as this book is concerned, most of the code is freely redistributable, either insource or binary form, and neither we nor O’Reilly retain any right on any derived
works All the programs are available at ftp://ftp.ora.com/pub/examples/linux/drivers/, and the exact license terms are stated in the LICENSE file in the same directory.
Joining the Kernel Development Community
As you begin writing modules for the Linux kernel, you become part of a larger munity of developers Within that community, you can find not only people engaged
com-in similar work, but also a group of highly committed engcom-ineers workcom-ing towardmaking Linux a better system These people can be a source of help, ideas, and criti-cal review as well—they will be the first people you will likely turn to when you arelooking for testers for a new driver
The central gathering point for Linux kernel developers is the linux-kernel mailing
list All major kernel developers, from Linus Torvalds on down, subscribe to this list.Please note that the list is not for the faint of heart: traffic as of this writing can run
up to 200 messages per day or more Nonetheless, following this list is essential forthose who are interested in kernel development; it also can be a top-quality resourcefor those in need of kernel development help
To join the linux-kernel list, follow the instructions found in the linux-kernel
mail-ing list FAQ: http://www.tux.org/lkml Read the rest of the FAQ while you are at it;
there is a great deal of useful information there Linux kernel developers are busypeople, and they are much more inclined to help people who have clearly done theirhomework first
Overview of the Book
From here on, we enter the world of kernel programming Chapter 2 introducesmodularization, explaining the secrets of the art and showing the code for runningmodules Chapter 3 talks about char drivers and shows the complete code for a
Trang 31memory-based device driver that can be read and written for fun Using memory asthe hardware base for the device allows anyone to run the sample code without theneed to acquire special hardware.
Debugging techniques are vital tools for the programmer and are introduced inChapter 4 Equally important for those who would hack on contemporary kernels isthe management of concurrency and race conditions Chapter 5 concerns itself withthe problems posed by concurrent access to resources and introduces the Linuxmechanisms for controlling concurrency
With debugging and concurrency management skills in place, we move to advanced
features of char drivers, such as blocking operations, the use of select, and the tant ioctl call; these topics are the subject of Chapter 6.
impor-Before dealing with hardware management, we dissect a few more of the kernel’ssoftware interfaces: Chapter 7 shows how time is managed in the kernel, andChapter 8 explains memory allocation
Next we focus on hardware Chapter 9 describes the management of I/O ports andmemory buffers that live on the device; after that comes interrupt handling, inChapter 10 Unfortunately, not everyone is able to run the sample code for these
chapters, because some hardware support is actually needed to test the software
interface interrupts We’ve tried our best to keep required hardware support to aminimum, but you still need some simple hardware, such as a standard parallel port,
to work with the sample code for these chapters
Chapter 11 covers the use of data types in the kernel and the writing of portablecode
The second half of the book is dedicated to more advanced topics We start by ting deeper into the hardware and, in particular, the functioning of specific periph-eral buses Chapter 12 covers the details of writing drivers for PCI devices, andChapter 13 examines the API for working with USB devices
get-With an understanding of peripheral buses in place, we can take a detailed look at theLinux device model, which is the abstraction layer used by the kernel to describe thehardware and software resources it is managing Chapter 14 is a bottom-up look atthe device model infrastructure, starting with the kobject type and working up fromthere It covers the integration of the device model with real hardware; it then usesthat knowledge to cover topics like hot-pluggable devices and power management
In Chapter 15, we take a diversion into Linux memory management This chapter
shows how to map kernel memory into user space (the mmap system call), map user memory into kernel space (with get_user_pages), and how to map either kind of
memory into device space (to perform direct memory access [DMA] operations)
Trang 32Our understanding of memory will be useful for the following two chapters, whichcover the other major driver classes Chapter 16 introduces block drivers and showshow they are different from the char drivers we have worked with so far ThenChapter 17 gets into the writing of network drivers We finish up with a discussion
of serial drivers (Chapter 18) and a bibliography
Trang 33con-a complete (if relcon-atively useless)module, con-and look con-at some of the bcon-asic code shcon-ared
by all modules Developing such expertise is an essential foundation for any kind ofmodularized driver To avoid throwing in too many concepts at once, this chaptertalks only about modules, without referring to any specific device class
All the kernel items (functions, variables, header files, and macros)that are duced here are described in a reference section at the end of the chapter
intro-Setting Up Your Test System
Starting with this chapter, we present example modules to demonstrate ming concepts (All of these examples are available on O’Reilly’s FTP site, asexplained in Chapter 1.)Building, loading, and modifying these examples are a goodway to improve your understanding of how drivers work and interact with the kernel.The example modules should work with almost any 2.6.x kernel, including thoseprovided by distribution vendors However, we recommend that you obtain a “main-
program-line” kernel directly from the kernel.org mirror network, and install it on your
sys-tem Vendor kernels can be heavily patched and divergent from the mainline; attimes, vendor patches can change the kernel API as seen by device drivers If you arewriting a driver that must work on a particular distribution, you will certainly want
to build and test against the relevant kernels But, for the purpose of learning aboutdriver writing, a standard kernel is best
Regardless of the origin of your kernel, building modules for 2.6.x requires that youhave a configured and built kernel tree on your system This requirement is a changefrom previous versions of the kernel, where a current set of header files was suffi-cient 2.6 modules are linked against object files found in the kernel source tree; theresult is a more robust module loader, but also the requirement that those object files
Trang 34be available So your first order of business is to come up with a kernel source tree
(either from the kernel.org network or your distributor’s kernel source package),
build a new kernel, and install it on your system For reasons we’ll see later, life isgenerally easiest if you are actually running the target kernel when you build yourmodules, though this is not required
You should also give some thought to where you do your module experimentation, development, and testing We have done our best to make our example modules safe and correct, but the possibility of bugs is always present Faults in kernel code can bring about the demise of a user process or, occasionally, the entire system They do not normally create more serious problems, such as disk corruption.
Nonetheless, it is advisable to do your kernel experimentation on a system that does not contain data that you cannot afford to lose, and that does not perform essential services Kernel hackers typically keep
a “sacrificial” system around for the purpose of testing new code.
So, if you do not yet have a suitable system with a configured and built kernel sourcetree on disk, now would be a good time to set that up We’ll wait Once that task istaken care of, you’ll be ready to start playing with kernel modules
The Hello World Module
Many programming books begin with a “hello world” example as a way of showingthe simplest possible program This book deals in kernel modules rather than pro-grams; so, for the impatient reader, the following code is a complete “hello world”module:
This module defines two functions, one to be invoked when the module is loaded
into the kernel (hello_init)and one for when the module is removed (hello_exit) The
Trang 35module_init and module_exit lines use special kernel macros to indicate the role of these two functions Another special macro (MODULE_LICENSE)is used to tell the
kernel that this module bears a free license; without such a declaration, the kernelcomplains when the module is loaded
The printk function is defined in the Linux kernel and made available to modules; it behaves similarly to the standard C library function printf The kernel needs its own
printing function because it runs by itself, without the help of the C library The
module can call printk because, after insmod has loaded it, the module is linked to
the kernel and can access the kernel’s public symbols (functions and variables, asdetailed in the next section) The string KERN_ALERT is the priority of the message.*
We’ve specified a high priority in this module, because a message with the defaultpriority might not show up anywhere useful, depending on the kernel version you
are running, the version of the klogd daemon, and your configuration You can
ignore this issue for now; we explain it in Chapter 4
You can test the module with the insmod and rmmod utilities, as shown below Note
that only the superuser can load and unload a module
root# rmmod hello
Goodbye cruel world
root#
Please note once again that, for the above sequence of commands to work, you musthave a properly configured and built kernel tree in a place where the makefile is able
to find it (/usr/src/linux-2.6.10 in the example shown) We get into the details of how
modules are built in the section “Compiling and Loading.”
According to the mechanism your system uses to deliver the message lines, your put may be different In particular, the previous screen dump was taken from a text
out-console; if you are running insmod and rmmod from a terminal emulator running
under the window system, you won’t see anything on your screen The message goes
to one of the system log files, such as /var/log/messages (the name of the actual file
* The priority is just a string, such as <1>, which is prepended to the printk format string Note the lack of a
comma after KERN_ALERT ; adding a comma there is a common and annoying typo (which, fortunately, is caught by the compiler).
Trang 36varies between Linux distributions) The mechanism used to deliver kernel messages
is described in Chapter 4
As you can see, writing a module is not as difficult as you might expect—at least, aslong as the module is not required to do anything worthwhile The hard part isunderstanding your device and how to maximize performance We go deeper intomodularization throughout this chapter and leave device-specific issues for laterchapters
Kernel Modules Versus Applications
Before we go further, it’s worth underlining the various differences between a kernelmodule and an application
While most small and medium-sized applications perform a single task from ning to end, every kernel module just registers itself in order to serve future requests,and its initialization function terminates immediately In other words, the task of themodule’s initialization function is to prepare for later invocation of the module’sfunctions; it’s as though the module were saying, “Here I am, and this is what I can
begin-do.” The module’s exit function (hello_exit in the example)gets invoked just before
the module is unloaded It should tell the kernel, “I’m not there anymore; don’t ask
me to do anything else.” This kind of approach to programming is similar to driven programming, but while not all applications are event-driven, each and everykernel module is Another major difference between event-driven applications andkernel code is in the exit function: whereas an application that terminates can be lazy
event-in releasevent-ing resources or avoids clean up altogether, the exit function of a module
must carefully undo everything the init function built up, or the pieces remain
around until the system is rebooted
Incidentally, the ability to unload a module is one of the features of modularizationthat you’ll most appreciate, because it helps cut down development time; you cantest successive versions of your new driver without going through the lengthy shut-down/reboot cycle each time
As a programmer, you know that an application can call functions it doesn’t define:the linking stage resolves external references using the appropriate library of func-
tions printf is one of those callable functions and is defined in libc A module, on the
other hand, is linked only to the kernel, and the only functions it can call are the
ones exported by the kernel; there are no libraries to link to The printk function used in hello.c earlier, for example, is the version of printf defined within the kernel
and exported to modules It behaves similarly to the original function, with a fewminor differences, the main one being lack of floating-point support
Figure 2-1 shows how function calls and function pointers are used in a module toadd new functionality to a running kernel
Trang 37Because no library is linked to modules, source files should never include the usual
header files, <stdarg.h> and very special situations being the only exceptions Only
functions that are actually part of the kernel itself may be used in kernel modules.Anything related to the kernel is declared in headers found in the kernel source tree
you have set up and configured; most of the relevant headers live in include/linux and include/asm, but other subdirectories of include have been added to host material
associated to specific kernel subsystems
The role of individual kernel headers is introduced throughout the book as each ofthem is needed
Another important difference between kernel programming and application gramming is in how each environment handles faults: whereas a segmentation fault
pro-is harmless during application development and a debugger can always be used totrace the error to the problem in the source code, a kernel fault kills the current pro-cess at least, if not the whole system We see how to trace kernel errors in Chapter 4
User Space and Kernel Space
A module runs in kernel space, whereas applications run in user space This concept
is at the base of operating systems theory
The role of the operating system, in practice, is to provide programs with a tent view of the computer’s hardware In addition, the operating system mustaccount for independent operation of programs and protection against unauthorizedaccess to resources This nontrivial task is possible only if the CPU enforces protec-tion of system software from the applications
consis-Figure 2-1 Linking a module to the kernel
init function
add_disk()
request() block_device ops
cleanup function
blk_cleanup_queue() request_queue_
struct gendisk
Data operation Data pointer Function call Function pointer
Multiple functions Single functions Data
Trang 38Every modern processor is able to enforce this behavior The chosen approach is toimplement different operating modalities (or levels)in the CPU itself The levels havedifferent roles, and some operations are disallowed at the lower levels; program codecan switch from one level to another only through a limited number of gates Unixsystems are designed to take advantage of this hardware feature, using two such lev-els All current processors have at least two protection levels, and some, like the x86family, have more levels; when several levels exist, the highest and lowest levels are
used Under Unix, the kernel executes in the highest level (also called supervisor mode), where everything is allowed, whereas applications execute in the lowest level (the so-called user mode), where the processor regulates direct access to hardware
and unauthorized access to memory
We usually refer to the execution modes as kernel space and user space These terms
encompass not only the different privilege levels inherent in the two modes, but alsothe fact that each mode can have its own memory mapping—its own addressspace—as well
Unix transfers execution from user space to kernel space whenever an applicationissues a system call or is suspended by a hardware interrupt Kernel code executing asystem call is working in the context of a process—it operates on behalf of the call-ing process and is able to access data in the process’s address space Code that han-dles interrupts, on the other hand, is asynchronous with respect to processes and isnot related to any particular process
The role of a module is to extend kernel functionality; modularized code runs in nel space Usually a driver performs both the tasks outlined previously: some func-tions in the module are executed as part of system calls, and some are in charge ofinterrupt handling
ker-Concurrency in the Kernel
One way in which kernel programming differs greatly from conventional applicationprogramming is the issue of concurrency Most applications, with the notable excep-tion of multithreading applications, typically run sequentially, from the beginning tothe end, without any need to worry about what else might be happening to changetheir environment Kernel code does not run in such a simple world, and even thesimplest kernel modules must be written with the idea that many things can be hap-pening at once
There are a few sources of concurrency in kernel programming Naturally, Linux tems run multiple processes, more than one of which can be trying to use your driver
sys-at the same time Most devices are capable of interrupting the processor; interrupthandlers run asynchronously and can be invoked at the same time that your driver istrying to do something else Several software abstractions (such as kernel timers,introduced in Chapter 7)run asynchronously as well Moreover, of course, Linux
Trang 39can run on symmetric multiprocessor (SMP)systems, with the result that your drivercould be executing concurrently on more than one CPU Finally, in 2.6, kernel codehas been made preemptible; this change causes even uniprocessor systems to havemany of the same concurrency issues as multiprocessor systems.
As a result, Linux kernel code, including driver code, must be reentrant—it must be
capable of running in more than one context at the same time Data structures must
be carefully designed to keep multiple threads of execution separate, and the codemust take care to access shared data in ways that prevent corruption of the data.Writing code that handles concurrency and avoids race conditions (situations inwhich an unfortunate order of execution causes undesirable behavior)requiresthought and can be tricky Proper management of concurrency is required to writecorrect kernel code; for that reason, every sample driver in this book has been writ-ten with concurrency in mind The techniques used are explained as we come tothem; Chapter 5 has also been dedicated to this issue and the kernel primitives avail-able for concurrency management
A common mistake made by driver programmers is to assume that concurrency isnot a problem as long as a particular segment of code does not go to sleep (or
“block”) Even in previous kernels (which were not preemptive), this assumptionwas not valid on multiprocessor systems In 2.6, kernel code can (almost)neverassume that it can hold the processor over a given stretch of code If you do not writeyour code with concurrency in mind, it will be subject to catastrophic failures thatcan be exceedingly difficult to debug
The Current Process
Although kernel modules don’t execute sequentially as applications do, most actionsperformed by the kernel are done on behalf of a specific process Kernel code canrefer to the current process by accessing the global itemcurrent, defined in <asm/ current.h>, which yields a pointer tostruct task_struct, defined by <linux/sched.h>.
Thecurrentpointer refers to the process that is currently executing During the
exe-cution of a system call, such as open or read, the current process is the one that
invoked the call Kernel code can use process-specific information by usingcurrent,
if it needs to do so An example of this technique is presented in Chapter 6
Actually, current is not truly a global variable The need to support SMP systemsforced the kernel developers to develop a mechanism that finds the current process onthe relevant CPU This mechanism must also be fast, since references tocurrenthap-pen frequently The result is an architecture-dependent mechanism that, usually,hides a pointer to thetask_struct structure on the kernel stack The details of theimplementation remain hidden to other kernel subsystems though, and a device
driver can just include <linux/sched.h> and refer to thecurrentprocess For example,
Trang 40the following statement prints the process ID and the command name of the currentprocess by accessing certain fields instruct task_struct:
printk(KERN_INFO "The process is \"%s\" (pid %i)\n",
current->comm, current->pid);
The command name stored in current->commis the base name of the program file(trimmed to 15 characters if need be) that is being executed by the current process
A Few Other Details
Kernel programming differs from user-space programming in many ways We’llpoint things out as we get to them over the course of the book, but there are a fewfundamental issues which, while not warranting a section of their own, are worth amention So, as you dig into the kernel, the following issues should be kept in mind.Applications are laid out in virtual memory with a very large stack area The stack, ofcourse, is used to hold the function call history and all automatic variables created bycurrently active functions The kernel, instead, has a very small stack; it can be assmall as a single, 4096-byte page Your functions must share that stack with theentire kernel-space call chain Thus, it is never a good idea to declare large auto-matic variables; if you need larger structures, you should allocate them dynamically
at call time
Often, as you look at the kernel API, you will encounter function names starting with
a double underscore ( ) Functions so marked are generally a low-level component
of the interface and should be used with caution Essentially, the double underscoresays to the programmer: “If you call this function, be sure you know what you aredoing.”
Kernel code cannot do floating point arithmetic Enabling floating point wouldrequire that the kernel save and restore the floating point processor’s state on eachentry to, and exit from, kernel space—at least, on some architectures Given thatthere really is no need for floating point in kernel code, the extra overhead is notworthwhile
Compiling and Loading
The “hello world” example at the beginning of this chapter included a brief stration of building a module and loading it into the system There is, of course, a lotmore to that whole process than we have seen so far This section provides moredetail on how a module author turns source code into an executing subsystem withinthe kernel