Writing Linux Device Drivers in Assembly Language - 2002.pdf
(
816 KB
)
Pobierz
LDD
Writing Linux Device Drivers in Assembly Language
(Full Contents)
0 Preface and Introduction ............................................................................. 3
0.1 Randy’s Introduction ......................................................................... 3
0.2 Why Assembly Language? ............................................................... 3
0.3 Assembly Language Isn’t That Bad .................................................. 4
1 An Introduction to Device Drivers ............................................................. 5
2 Building and Running Modules .................................................................. 7
2.1 The "Hello World" Driver Module ................................................... 8
2.2 Compiling and Linking Drivers ........................................................ 13
2.3 Version Dependency ......................................................................... 14
2.4 Kernel Modules vs. Applications ...................................................... 16
2.5 Kernel Stack Space and The Current Process .................................. 18
2.6 Compiling and Loading .................................................................... 19
2.6.1 A Make File for SKULL .......................................................... 19
2.7 Version Dependency and Installation Issues .................................... 20
2.8 Platform Dependency ........................................................................ 20
2.9 The Kernel Symbol Table ................................................................. 21
2.10 Initialization and Shutdown ............................................................ 21
2.11 Error Handling in init_module ........................................................ 22
2.12 The Usage Count ............................................................................. 23
2.13 Resource Allocation (I/O Ports and Memory) ................................ 24
2.14 Automatic and Manual Configuration ............................................ 26
2.15 The SKULL Module ....................................................................... 27
2.16 Kernel Versions and HLA Header Files ......................................... 38
2.16.1 Converting C Header Files to HLA and Updating Header Files 39
2.16.2 Converting C Structs to HLA Records ................................... 41
2.16.3 C Calling Sequences and Wrapper Functions/Macros ........... 43
2.16.4 Kernel Types vs. User Types .................................................. 46
2.17 Some Simple Debug Tools ............................................................. 46
3 Character Drivers ........................................................................................ 51
3.1 The Design of scullc ......................................................................... 51
3.2 Major and Minor Numbers ............................................................... 52
3.3 Dynamic Allocation of Major Numbers ........................................... 53
3.4 Removing a Driver From the System ............................................... 56
3.5 dev_t and kdev_t ............................................................................... 56
3.6 File Operations .................................................................................. 58
3.6.1 The llseek Function .................................................................. 65
3.6.2 The read Function ..................................................................... 66
3.7 The write Function ............................................................................ 66
3.8 The readdir Function ......................................................................... 67
3.8.1 The poll Function ..................................................................... 67
3.8.2 The _ioctl Function ................................................................... 67
3.8.3 The mmap Function .................................................................. 68
3.8.4 The open Function .................................................................... 68
3.8.5 The flush Function .................................................................... 68
© 2002, By Randall Hyde
Page 1
LDDTOC.fm
3.8.6 The release Function ................................................................. 68
3.8.7 The fsync Function ................................................................... 68
3.8.8 The fasync Function ................................................................. 69
3.8.9 The lock Function ..................................................................... 69
3.8.10 The readv and writev Functions ............................................. 69
3.8.11 The owner Field ...................................................................... 70
3.9 The file Record .................................................................................. 70
3.9.1 file.f_mode : linux.mode_t ....................................................... 70
3.9.2 file.f_pos : linux.loff_t .............................................................. 70
3.9.3 file.f_flags : dword ................................................................... 70
3.9.4 file.f_op : linux.file_operations ................................................ 71
3.9.5 file.private_data : dword ........................................................... 71
3.9.6 file.f_dentry : linux.dentry ........................................................ 71
3.10 Open and Release ............................................................................ 71
3.10.1 The Open Procedure ............................................................... 71
3.10.2 The release Procedure ............................................................. 78
3.10.3 Kernel Memory Management (kmalloc and kfree) ................ 78
3.10.4 The scull_device Data Type ................................................... 79
3.10.5 A (Very) Brief Introduction to Race Conditions .................... 80
3.10.6 The read and write Procedures ............................................... 82
3.11 The scullc Driver ............................................................................. 92
3.11.1 The scullc.hhf Header File ...................................................... 92
3.12 The scullc.hla Source File ............................................................... 94
3.13 Debugging Techniques .................................................................... 108
3.13.1 Code Reviews ......................................................................... 108
3.13.2 Debugging By Printing ........................................................... 110
3.13.2.1 linux.printk ................................................................... 110
3.13.2.2 Turning Debug Messages On and Off ......................... 111
3.13.2.3 Debug Zones ................................................................ 112
3.13.3 Debugging by Querying ......................................................... 113
Page 2
© 2001, By Randall Hyde
Beta Draft - Do not distribute
Linux Device Drivers in Assembly
Writing Linux Device Drivers in Assembly Language
Written by Randall Hyde
0
Preface and Introduction
This document will attempt to describe how to write Linux device drivers (modules) in assembly lan-
guage. This document is not self-contained; that is, you cannot learn everything you need to know about
Linux device drivers (assembly or otherwise) from this document. Instead, this document is based on the
text "Linux Device Drivers, Second Edition" by Rubini & Corbet (published by O’Reilly & Associates,
ISBN 0-596-00008-1). That text explains how to write device drivers using C, this document parallels that
text, converting the examples to assembly language. However, to keep this document relatively short, this
document does not copy the information that is language-independent from the text. Therefore, you’ll need
a copy of that text to read along with this document so the whole thing makes sense.
Rubini & Corbet have graciously chosen to make their text freely available under the GNU Free Docu-
mentation License 1.1. Therefore, this text inherits that license. You can learn more about the GNU Free
Documentation License from
http://www.oreilly.com/catalog/linuxdrive2/chapter/licenseinfo.html
The programming examples in this text are generally translations of the C code appearing in "Linux
Device Drivers" so they also inherit Rubini & Corbet’s licensing terms. Please see the section on licensing
in "Linux Device Drivers, Second Edition," orthe text file LICENSE with the distributed software for more
details on the licensing terms.
If you’re not reading this copy of "Webster" you’ll probably want to check out the Webster website at
http://webster.cs.ucr.edu
where you’ll find the latest copy of this text and its accompanying software.
0.1
Randy’s Introduction
As an embedded engineer, I’ve had the opportunity to deal with Linux device drivers in the past (back
around Linux 1.x when the device driver world was considerably different). Most of the device drivers for
Linux I’d dealt with were quite simple and generally involved tweaking other device drivers to get the func-
tionality I was interested in. At one point I needed to modernize my Linux device driver skills (Linux v2.x
does things way differently). As I mastered the material, I wrote about it in this document so I could share
my knowledge with the world at large.
0.2
Why Assembly Language?
is a good start, but as
I get tired reading I tend to gloss over important details. I’m not the kind of person who can read through a
text once or twice and completely master the material; I need to actually
Linux Device Drivers
before I feel I’ve mas-
tered the material. Furthermore, I’ve never been convinced that I could learn the material well by simply
typing code out of a textbook; to truly learn the material I’ve always had to write my own code implement-
ing the concepts from the text. The problem with this approach when using a text like
write code
Linux Device Drivers,
is that it covers a lot of material dealing with real-world devices. Taking the time to master
the particular peripherals on my development system (specific hard drives, network interface cards, etc.)
doesn’t seem like a good use of my time. Dreaming up new pseudo devices (like the ones Rubini & Corbet
This document is covered by the GNU Free Documentation License v1.1
Page 3
Rather than take the "just hack an existing driver" approach, I wanted to learn Linux device drivers
inside and out. Reading (and doing the examples in) a book like
Second Edition
Linux Device Drivers in Assembly
use in their examples) didn’t seem particularly productive, either. What to do? It occurred to me that if I
were to translate all the examples in C to a different programming language, I would have to really under-
stand material. Of all the languages besides C, assembly is probably the most practical language with which
one can write device drivers (practical from a capability point of view, as opposed to a software engineering
point of view). The only reasonable language choice for Linux device drivers other than C is assembly lan-
guage (that is, I *know* that I’d be able to write my drivers in assembly since GCC emits assembly code;
I’m not sure at all that it would be possible to do this in some other language I have access to).
Rewriting Rubini & Corbet’s examples in a different language certainly helps me understand what
they’re doing; rewriting their examples in assembly language really forces me to understand the concepts
because C hides a lot of gory details from you (which Rubini & Corbet generally don’t bother to explain).
So that was my second reason for using assembly; by using assembly to write these drivers I
really
pro-
gramming, as well. You won’t fully appreciate the complexity of the Linux system until you’ve converted a
large number of C header files to assembly language (and verified that the conversion is correct).
Note that all the examples in this text are pure assembly language. I don’t write a major portion of the
driver in C and then call some small assembly language function to handle some operation. That would
defeat the purpose for (my) using assembly language in the first place, that is, forcing me to really learn this
stuff.
Of course, many people really want to know how to write Linux device drivers in assembly language.
Either they prefer assembly over C (and many people do, believe it or not), or they need the efficiency or
device control capabilities that only assembly language provides. Such individuals will probably find this
document enlightening. While those wanting more efficient code or more capbility could probably use the
C+assembly approach, they should still find this document interesting.
Of course, any die-hard Unix/Linux fan is probably screaming "don’t, don’t, don’t" at this point. "Why
on Earth would anyone be crazy enough to write a document about assembly language drivers for Linux? "
they’re probably saying. "Doesn’t this fool (me) know that Linux runs on different platforms and assembly
drivers won’t be portable?" Of course I realize this. I’m also assuming that anyone bright enough to write a
Linux device driver
Linux
realizes this. Nevertheless, there are many reasons for going ahead and writing a
device driver in assembly, portability be damned. Of course, portability isn’t that much of an issue to most
people since the vast majority of Linux systems use the x86 processor anyway (and, most likely, the devices
that such people are writing drivers for may only work on x86 systems anyway).
0.3
Assembly Language Isn’t
That
Bad
Linux & Unix programmers have a pathological fear of assembly language. Part of the reason for this
fear is the aforementioned portability issue. *NIX programmers tend to write programs that run on different
systems and assembly is an absolute no-no for those attempting to write portable applications. In fact, how-
ever, most *NIX programmers only write code that runs on Intel-based systems, so portability isn’t
that
underdocumented and it isn’t entirely robust.
Another assembler that has become available for Linux is NASM. While much better than Gas in terms of
usability, NASM is still a bit of work to learn and use. Certainly, your average C programmer isn’t going to
pick up NASM programming overnight. There are some other (x86) assemblers available for Linux, but I’m
going to use HLA in this document.
HLA (the High Level Assembler) is an assembler I originally designed for teaching assembly language
programming at UC Riverside. This assembler is public domain and runs under Windows and Linux. It
contains comprehensive documentation and there’s even a University-quality textbook ("The Art of Assem-
bly Language Programming") that newcomers to assembly can use to learn assembly and HLA.
I’m using HLA in the examples appearing herein for several reasons:
way
Page 4
Version: 4/21/02
Written by Randall Hyde
have to
know what’s going on. This experience was valuable not only because it forced me to learn Linux device
drivers to a depth I would have never otherwise attained, but it also taught me a lot of in-depth
also
much of an issue.
A second issue facing Linux programmers who want to use assembly is the toolset. Traditionally,
assemblers available for Linux have been very bad. There’s Gas (as), the tool that’s really intended only for
processing GCC’s output. Most people attempting to learn Gas give up in short order and go back to their C
code. Gas has many problems, not the least of which it’s
Linux Device Drivers in Assembly
• I designed and wrote HLA; so allow me to toot my own horn,
• HLA source code is quite a bit more readable than other assembly code,
• HLA includes lots of useful libary routines,
• HLA is easy to learn by those who know C or Pascal,.
• HLA is far more powerful than the other assemblers available for Linux.
For more information on HLA, to download HLA, or to read "The Art of Assembly Language Program-
ming" go to the Webster website at
http://webster.cs.ucr.edu
1
An Introduction to Device Drivers
(LDD2), Chapter One, spends a fair amount of time discussing
the role and position of device drivers in the system. Much of the material in this chapter is independent of
implementation language, so I’ll refer you to that text for more details.
There are, however, a couple of points that are made in LDD2 that are worth repeating here. First, this
document, like LDD2, deals with device drivers implemented as
(rather than device drivers that are
compiled in with the kernel). Modules have several advantages over traditional device drivers including: (1)
they are easier to write, test, and debug, (2) a (super) user can dynamically load and unload them at run-time,
(3) modules are not subject to the GPL as are device drivers compiled into the system; hence device driver
writers are not compelled to give away their source code which might leave them at a commercial disadvan-
tage.
Rubini & Corbet graciously grant permission to use the code in their book on the condition that any
derived code maintain some comments describing the origin of that code. I usually put my stuff directly in
the public domain, but since my code is (roughly) based on their code, I will keep the copyright on this stuff
and grant the same license. That is, you many use any of the code accompanying this document as long as
you maintain comments that describe its source (specifically, LDD2 and Rubini & Corbet, plus mentioning
the fact that it’s an assembly translation by R. Hyde).
In chapter one, Rubini & Corbet (R&C here on out) suggest that you join the Kernel Development Com-
munity and share your work. While this is a good idea, I’d strongly recommend a flame-resistant suit if
you’re going to submit drivers written in assembly language to the Linux community at large. I anticipate
that assembly drivers will not be well-received by the Linux/Unix community. Don’t say you weren’t
warned.
modules
This document is covered by the GNU Free Documentation License v1.1
Page 5
Linux Device Drivers, Second Edition
Plik z chomika:
elrafb
Inne pliki z tego folderu:
Writing Device Drivers.pdf
(1363 KB)
Prentice Hall Essential Linux Device Drivers Apr 2008.chm
(4176 KB)
Linux-Device_Drivers.pdf
(7537 KB)
Device Driver Writing In Linux.pdf
(783 KB)
[OReilly - 2005] Linux Device Drivers, 3rd Edition.pdf
(6896 KB)
Inne foldery tego chomika:
Embedded
Kernel
RTOS
Zgłoś jeśli
naruszono regulamin