-
Notifications
You must be signed in to change notification settings - Fork 1
/
lkmpg.html
5217 lines (4109 loc) · 173 KB
/
lkmpg.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
The Linux Kernel Module Programming Guide
Peter Jay Salzman
Michael Burian
Ori Pomerantz
Copyright © 2001 Peter Jay Salzman
2007-05-18 ver 2.6.4
The Linux Kernel Module Programming Guide is a free book; you may
reproduce and/or modify it under the terms of the Open Software License,
version 1.1. You can obtain a copy of this license at
http://opensource.org/licenses/osl.php.
This book is distributed in the hope it will be useful, but without any
warranty, without even the implied warranty of merchantability or
fitness for a particular purpose.
The author encourages wide distribution of this book for personal or
commercial use, provided the above copyright notice remains intact and
the method adheres to the provisions of the Open Software License. In
summary, you may copy and distribute this book free of charge or for a
profit. No explicit permission is required from the author for
reproduction of this book in any medium, physical or electronic.
Derivative works and translations of this document must be placed under
the Open Software License, and the original copyright notice must remain
intact. If you have contributed new material to this book, you must make
the material and source code available for your revisions. Please make
revisions and updates available directly to the document maintainer,
Peter Jay Salzman <[email protected] <mailto:[email protected]>>. This will allow
for the merging of updates and provide consistent revisions to the Linux
community.
If you publish or distribute this book commercially, donations,
royalties, and/or printed copies are greatly appreciated by the author
and the Linux Documentation Project <http://www.tldp.org> (LDP).
Contributing in this way shows your support for free software and the
LDP. If you have questions or comments, please contact the address above.
------------------------------------------------------------------------
*Table of Contents*
Foreword <#AEN25>
1. Authorship <#AEN27>
2. Versioning and Notes <#AEN30>
3. Acknowledgements <#AEN35>
1. Introduction <#AEN38>
1.1. What Is A Kernel Module? <#AEN40>
1.2. How Do Modules Get Into The Kernel? <#AEN44>
2. Hello World <#AEN119>
2.1. Hello, World (part 1): The Simplest Module <#AEN121>
2.2. Compiling Kernel Modules <#AEN181>
2.3. Hello World (part 2) <#HELLO2>
2.4. Hello World (part 3): The __init and __exit Macros <#AEN245>
2.5. Hello World (part 4): Licensing and Module Documentation <#AEN279>
2.6. Passing Command Line Arguments to a Module <#AEN323>
2.7. Modules Spanning Multiple Files <#AEN351>
2.8. Building modules for a precompiled kernel <#AEN380>
3. Preliminaries <#AEN425>
3.1. Modules vs Programs <#AEN427>
4. Character Device Files <#AEN567>
4.1. Character Device Drivers <#AEN569>
5. The /proc File System <#AEN708>
5.1. The /proc File System <#AEN710>
5.2. Read and Write a /proc File <#AEN769>
5.3. Manage /proc file with standard filesystem <#AEN810>
5.4. Manage /proc file with seq_file <#AEN861>
6. Using /proc For Input <#AEN885>
6.1. TODO: Write a chapter about sysfs <#AEN887>
7. Talking To Device Files <#AEN890>
7.1. Talking to Device Files (writes and IOCTLs) <#AEN892>
8. System Calls <#AEN976>
8.1. System Calls <#AEN978>
9. Blocking Processes <#AEN1050>
9.1. Blocking Processes <#AEN1052>
10. Replacing Printks <#AEN1159>
10.1. Replacing printk <#AEN1161>
10.2. Flashing keyboard LEDs <#AEN1194>
11. Scheduling Tasks <#AEN1209>
11.1. Scheduling Tasks <#AEN1211>
12. Interrupt Handlers <#INTERRUPTHANDLERS>
12.1. Interrupt Handlers <#AEN1256>
13. Symmetric Multi Processing <#AEN1324>
13.1. Symmetrical Multi-Processing <#AEN1326>
14. Common Pitfalls <#AEN1350>
14.1. Common Pitfalls <#AEN1352>
A. Changes: 2.0 To 2.2 <#AEN1387>
A.1. Changes between 2.4 and 2.6 <#AEN1389>
B. Where To Go From Here <#AEN1403>
B.1. Where From Here? <#AEN1405>
Index <#DOC-INDEX>
*List of Figures*
5-1. How seq_file works <#AEN868>
*List of Examples*
2-1. hello-1.c <#AEN128>
2-2. Makefile for a basic kernel module <#AEN189>
2-3. hello-2.c <#AEN232>
2-4. Makefile for both our modules <#AEN237>
2-5. hello-3.c <#AEN275>
2-6. hello-4.c <#AEN319>
2-7. hello-5.c <#AEN345>
2-8. start.c <#AEN361>
2-9. stop.c <#AEN369>
2-10. Makefile <#AEN374>
4-1. chardev.c <#AEN687>
5-1. procfs1.c <#AEN765>
5-2. procfs2.c <#AEN806>
5-3. procfs3.c <#AEN853>
5-4. procfs4.c <#AEN872>
7-1. chardev.c <#AEN951>
7-2. chardev.h <#AEN959>
7-3. ioctl.c <#AEN972>
8-1. syscall.c <#AEN1046>
9-1. sleep.c <#AEN1151>
9-2. cat_noblock.c <#AEN1155>
10-1. print_string.c <#AEN1190>
10-2. kbleds.c <#AEN1201>
11-1. sched.c <#AEN1250>
12-1. intrpt.c <#AEN1320>
------------------------------------------------------------------------
Foreword
1. Authorship
The Linux Kernel Module Programming Guide was originally written for the
2.2 kernels by Ori Pomerantz. Eventually, Ori no longer had time to
maintain the document. After all, the Linux kernel is a fast moving
target. Peter Jay Salzman took over maintenance and updated it for the
2.4 kernels. Eventually, Peter no longer had time to follow developments
with the 2.6 kernel, so Michael Burian became a co-maintainer to update
the document for the 2.6 kernels.
------------------------------------------------------------------------
2. Versioning and Notes
The Linux kernel is a moving target. There has always been a question
whether the LKMPG should remove deprecated information or keep it around
for historical sake. Michael Burian and I decided to create a new branch
of the LKMPG for each new stable kernel version. So version LKMPG 2.4.x
will address Linux kernel 2.4 and LKMPG 2.6.x will address Linux kernel
2.6. No attempt will be made to archive historical information; a person
wishing this information should read the appropriately versioned LKMPG.
The source code and discussions should apply to most architectures, but
I can't promise anything. One exception is Chapter 12
<#INTERRUPTHANDLERS>, Interrupt Handlers, which should not work on any
architecture except for x86.
------------------------------------------------------------------------
3. Acknowledgements
The following people have contributed corrections or good suggestions:
Ignacio Martin, David Porter, Daniele Paolo Scarpazza, Dimo Velev,
Francois Audeon and Horst Schirmeier.
------------------------------------------------------------------------
Chapter 1. Introduction
1.1. What Is A Kernel Module?
So, you want to write a kernel module. You know C, you've written a few
normal programs to run as processes, and now you want to get to where
the real action is, to where a single wild pointer can wipe out your
file system and a core dump means a reboot.
What exactly is a kernel module? Modules are pieces of code that can be
loaded and unloaded into the kernel upon demand. They extend the
functionality of the kernel without the need to reboot the system. For
example, one type of module is the device driver, which allows the
kernel to access hardware connected to the system. Without modules, we
would have to build monolithic kernels and add new functionality
directly into the kernel image. Besides having larger kernels, this has
the disadvantage of requiring us to rebuild and reboot the kernel every
time we want new functionality.
------------------------------------------------------------------------
1.2. How Do Modules Get Into The Kernel?
You can see what modules are already loaded into the kernel by running
*lsmod*, which gets its information by reading the file /proc/modules.
How do these modules find their way into the kernel? When the kernel
needs a feature that is not resident in the kernel, the kernel module
daemon kmod[1] <#FTN.AEN62> execs modprobe to load the module in.
modprobe is passed a string in one of two forms:
*
A module name like softdog or ppp.
*
A more generic identifier like char-major-10-30.
If modprobe is handed a generic identifier, it first looks for that
string in the file /etc/modprobe.conf.[2] <#FTN.AEN74> If it finds an
alias line like:
alias char-major-10-30 softdog
it knows that the generic identifier refers to the module softdog.ko.
Next, modprobe looks through the file /lib/modules/version/modules.dep,
to see if other modules must be loaded before the requested module may
be loaded. This file is created by *depmod -a* and contains module
dependencies. For example, msdos.ko requires the fat.ko module to be
already loaded into the kernel. The requested module has a dependency on
another module if the other module defines symbols (variables or
functions) that the requested module uses.
Lastly, modprobe uses insmod to first load any prerequisite modules into
the kernel, and then the requested module. modprobe directs insmod to
/lib/modules/version/[3] <#FTN.AEN87>, the standard directory for
modules. insmod is intended to be fairly dumb about the location of
modules, whereas modprobe is aware of the default location of modules,
knows how to figure out the dependencies and load the modules in the
right order. So for example, if you wanted to load the msdos module,
you'd have to either run:
insmod /lib/modules/2.6.11/kernel/fs/fat/fat.ko
insmod /lib/modules/2.6.11/kernel/fs/msdos/msdos.ko
or:
modprobe msdos
What we've seen here is: *insmod * requires you to pass it the full
pathname and to insert the modules in the right order, while *modprobe *
just takes the name, without any extension, and figures out all it needs
to know by parsing /lib/modules/version/modules.dep.
Linux distros provide modprobe, insmod and depmod as a package called
module-init-tools. In previous versions that package was called
modutils. Some distros also set up some wrappers that allow both
packages to be installed in parallel and do the right thing in order to
be able to deal with 2.4 and 2.6 kernels. Users should not need to care
about the details, as long as they're running recent versions of those
tools.
Now you know how modules get into the kernel. There's a bit more to the
story if you want to write your own modules which depend on other
modules (we calling this `stacking modules'). But this will have to wait
for a future chapter. We have a lot to cover before addressing this
relatively high-level issue.
------------------------------------------------------------------------
1.2.1. Before We Begin
Before we delve into code, there are a few issues we need to cover.
Everyone's system is different and everyone has their own groove.
Getting your first "hello world" program to compile and load correctly
can sometimes be a trick. Rest assured, after you get over the initial
hurdle of doing it for the first time, it will be smooth sailing thereafter.
------------------------------------------------------------------------
1.2.1.1. Modversioning
A module compiled for one kernel won't load if you boot a different
kernel unless you enable CONFIG_MODVERSIONS in the kernel. We won't go
into module versioning until later in this guide. Until we cover
modversions, the examples in the guide may not work if you're running a
kernel with modversioning turned on. However, most stock Linux distro
kernels come with it turned on. If you're having trouble loading the
modules because of versioning errors, compile a kernel with
modversioning turned off.
------------------------------------------------------------------------
1.2.1.2. Using X
It is highly recommended that you type in, compile and load all the
examples this guide discusses. It's also highly recommended you do this
from a console. You should not be working on this stuff in X.
Modules can't print to the screen like printf() can, but they can log
information and warnings, which ends up being printed on your screen,
but only on a console. If you insmod a module from an xterm, the
information and warnings will be logged, but only to your log files. You
won't see it unless you look through your log files. To have immediate
access to this information, do all your work from the console.
------------------------------------------------------------------------
1.2.1.3. Compiling Issues and Kernel Version
Very often, Linux distros will distribute kernel source that has been
patched in various non-standard ways, which may cause trouble.
A more common problem is that some Linux distros distribute incomplete
kernel headers. You'll need to compile your code using various header
files from the Linux kernel. Murphy's Law states that the headers that
are missing are exactly the ones that you'll need for your module work.
To avoid these two problems, I highly recommend that you download,
compile and boot into a fresh, stock Linux kernel which can be
downloaded from any of the Linux kernel mirror sites. See the Linux
Kernel HOWTO for more details.
Ironically, this can also cause a problem. By default, gcc on your
system may look for the kernel headers in their default location rather
than where you installed the new copy of the kernel (usually in
/usr/src/. This can be fixed by using gcc's -I switch.
------------------------------------------------------------------------
Chapter 2. Hello World
2.1. Hello, World (part 1): The Simplest Module
When the first caveman programmer chiseled the first program on the
walls of the first cave computer, it was a program to paint the string
`Hello, world' in Antelope pictures. Roman programming textbooks began
with the `Salut, Mundi' program. I don't know what happens to people who
break with this tradition, but I think it's safer not to find out. We'll
start with a series of hello world programs that demonstrate the
different aspects of the basics of writing a kernel module.
Here's the simplest module possible. Don't compile it yet; we'll cover
module compilation in the next section.
*Example 2-1. hello-1.c*
/*
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
Kernel modules must have at least two functions: a "start"
(initialization) function called init_module() which is called when the
module is insmoded into the kernel, and an "end" (cleanup) function
called cleanup_module() which is called just before it is rmmoded.
Actually, things have changed starting with kernel 2.3.13. You can now
use whatever name you like for the start and end functions of a module,
and you'll learn how to do this in Section 2.3 <#HELLO2>. In fact, the
new method is the preferred method. However, many people still use
init_module() and cleanup_module() for their start and end functions.
Typically, init_module() either registers a handler for something with
the kernel, or it replaces one of the kernel functions with its own code
(usually code to do something and then call the original function). The
cleanup_module() function is supposed to undo whatever init_module()
did, so the module can be unloaded safely.
Lastly, every kernel module needs to include linux/module.h. We needed
to include linux/kernel.h only for the macro expansion for the printk()
log level, KERN_ALERT, which you'll learn about in Section 2.1.1
<#INTRODUCINGPRINTK>.
------------------------------------------------------------------------
2.1.1. Introducing printk()
Despite what you might think, printk() was not meant to communicate
information to the user, even though we used it for exactly this purpose
in hello-1! It happens to be a logging mechanism for the kernel, and is
used to log information or give warnings. Therefore, each printk()
statement comes with a priority, which is the <1> and KERN_ALERT you
see. There are 8 priorities and the kernel has macros for them, so you
don't have to use cryptic numbers, and you can view them (and their
meanings) in linux/kernel.h. If you don't specify a priority level, the
default priority, DEFAULT_MESSAGE_LOGLEVEL, will be used.
Take time to read through the priority macros. The header file also
describes what each priority means. In practise, don't use number, like
<4>. Always use the macro, like KERN_WARNING.
If the priority is less than int console_loglevel, the message is
printed on your current terminal. If both *syslogd* and klogd are
running, then the message will also get appended to /var/log/messages,
whether it got printed to the console or not. We use a high priority,
like KERN_ALERT, to make sure the printk() messages get printed to your
console rather than just logged to your logfile. When you write real
modules, you'll want to use priorities that are meaningful for the
situation at hand.
------------------------------------------------------------------------
2.2. Compiling Kernel Modules
Kernel modules need to be compiled a bit differently from regular
userspace apps. Former kernel versions required us to care much about
these settings, which are usually stored in Makefiles. Although
hierarchically organized, many redundant settings accumulated in
sublevel Makefiles and made them large and rather difficult to maintain.
Fortunately, there is a new way of doing these things, called kbuild,
and the build process for external loadable modules is now fully
integrated into the standard kernel build mechanism. To learn more on
how to compile modules which are not part of the official kernel (such
as all the examples you'll find in this guide), see file
linux/Documentation/kbuild/modules.txt.
So, let's look at a simple Makefile for compiling a module named hello-1.c:
*Example 2-2. Makefile for a basic kernel module*
obj-m += hello-1.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
From a technical point of view just the first line is really necessary,
the "all" and "clean" targets were added for pure convenience.
Now you can compile the module by issuing the command *make *. You
should obtain an output which resembles the following:
hostname:~/lkmpg-examples/02-HelloWorld# make
make -C /lib/modules/2.6.11/build M=/root/lkmpg-examples/02-HelloWorld modules
make[1]: Entering directory `/usr/src/linux-2.6.11'
CC [M] /root/lkmpg-examples/02-HelloWorld/hello-1.o
Building modules, stage 2.
MODPOST
CC /root/lkmpg-examples/02-HelloWorld/hello-1.mod.o
LD [M] /root/lkmpg-examples/02-HelloWorld/hello-1.ko
make[1]: Leaving directory `/usr/src/linux-2.6.11'
hostname:~/lkmpg-examples/02-HelloWorld#
Note that kernel 2.6 introduces a new file naming convention: kernel
modules now have a .ko extension (in place of the old .o extension)
which easily distinguishes them from conventional object files. The
reason for this is that they contain an additional .modinfo section that
where additional information about the module is kept. We'll soon see
what this information is good for.
Use *modinfo hello-*.ko * to see what kind of information it is.
hostname:~/lkmpg-examples/02-HelloWorld# modinfo hello-1.ko
filename: hello-1.ko
vermagic: 2.6.11 preempt PENTIUMII 4KSTACKS gcc-3.3
depends:
Nothing spectacular, so far. That changes once we're using modinfo on
one of our the later examples, hello-5.ko .
hostname:~/lkmpg-examples/02-HelloWorld# modinfo hello-5.ko
filename: hello-5.ko
license: GPL
author: Peter Jay Salzman
vermagic: 2.6.11 preempt PENTIUMII 4KSTACKS gcc-3.3
depends:
parm: myintArray:An array of integers (array of int)
parm: mystring:A character string (charp)
parm: mylong:A long integer (long)
parm: myint:An integer (int)
parm: myshort:A short integer (short)
hostname:~/lkmpg-examples/02-HelloWorld#
Lot's of useful information to see here. An author string for
bugreports, license information, even a short description of the
parameters it accepts.
Additional details about Makefiles for kernel modules are available in
linux/Documentation/kbuild/makefiles.txt. Be sure to read this and the
related files before starting to hack Makefiles. It'll probably save you
lots of work.
Now it is time to insert your freshly-compiled module it into the kernel
with *insmod ./hello-1.ko* (ignore anything you see about tainted
kernels; we'll cover that shortly).
All modules loaded into the kernel are listed in /proc/modules. Go ahead
and cat that file to see that your module is really a part of the
kernel. Congratulations, you are now the author of Linux kernel code!
When the novelty wears off, remove your module from the kernel by using
*rmmod hello-1*. Take a look at /var/log/messages just to see that it
got logged to your system logfile.
Here's another exercise for the reader. See that comment above the
return statement in init_module()? Change the return value to something
negative, recompile and load the module again. What happens?
------------------------------------------------------------------------
2.3. Hello World (part 2)
As of Linux 2.4, you can rename the init and cleanup functions of your
modules; they no longer have to be called init_module() and
cleanup_module() respectively. This is done with the module_init() and
module_exit() macros. These macros are defined in linux/init.h. The only
caveat is that your init and cleanup functions must be defined before
calling the macros, otherwise you'll get compilation errors. Here's an
example of this technique:
*Example 2-3. hello-2.c*
/*
* hello-2.c - Demonstrating the module_init() and module_exit() macros.
* This is preferred over using init_module() and cleanup_module().
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
static int __init hello_2_init(void)
{
printk(KERN_INFO "Hello, world 2\n");
return 0;
}
static void __exit hello_2_exit(void)
{
printk(KERN_INFO "Goodbye, world 2\n");
}
module_init(hello_2_init);
module_exit(hello_2_exit);
So now we have two real kernel modules under our belt. Adding another
module is as simple as this:
*Example 2-4. Makefile for both our modules*
obj-m += hello-1.o
obj-m += hello-2.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
Now have a look at linux/drivers/char/Makefile for a real world example.
As you can see, some things get hardwired into the kernel (obj-y) but
where are all those obj-m gone? Those familiar with shell scripts will
easily be able to spot them. For those not, the obj-$(CONFIG_FOO)
entries you see everywhere expand into obj-y or obj-m, depending on
whether the CONFIG_FOO variable has been set to y or m. While we are at
it, those were exactly the kind of variables that you have set in the
linux/.config file, the last time when you said *make menuconfig* or
something like that.
------------------------------------------------------------------------
2.4. Hello World (part 3): The __init and __exit Macros
This demonstrates a feature of kernel 2.2 and later. Notice the change
in the definitions of the init and cleanup functions. The __init macro
causes the init function to be discarded and its memory freed once the
init function finishes for built-in drivers, but not loadable modules.
If you think about when the init function is invoked, this makes perfect
sense.
There is also an __initdata which works similarly to __init but for init
variables rather than functions.
The __exit macro causes the omission of the function when the module is
built into the kernel, and like __exit, has no effect for loadable
modules. Again, if you consider when the cleanup function runs, this
makes complete sense; built-in drivers don't need a cleanup function,
while loadable modules do.
These macros are defined in linux/init.h and serve to free up kernel
memory. When you boot your kernel and see something like Freeing unused
kernel memory: 236k freed, this is precisely what the kernel is freeing.
*Example 2-5. hello-3.c*
/*
* hello-3.c - Illustrating the __init, __initdata and __exit macros.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
static int hello3_data __initdata = 3;
static int __init hello_3_init(void)
{
printk(KERN_INFO "Hello, world %d\n", hello3_data);
return 0;
}
static void __exit hello_3_exit(void)
{
printk(KERN_INFO "Goodbye, world 3\n");
}
module_init(hello_3_init);
module_exit(hello_3_exit);
------------------------------------------------------------------------
2.5. Hello World (part 4): Licensing and Module Documentation
If you're running kernel 2.4 or later, you might have noticed something
like this when you loaded proprietary modules:
# insmod xxxxxx.o
Warning: loading xxxxxx.ko will taint the kernel: no license
See http://www.tux.org/lkml/#export-tainted for information about tainted modules
Module xxxxxx loaded, with warnings
In kernel 2.4 and later, a mechanism was devised to identify code
licensed under the GPL (and friends) so people can be warned that the
code is non open-source. This is accomplished by the MODULE_LICENSE()
macro which is demonstrated in the next piece of code. By setting the
license to GPL, you can keep the warning from being printed. This
license mechanism is defined and documented in linux/module.h:
/*
* The following license idents are currently accepted as indicating free
* software modules
*
* "GPL" [GNU Public License v2 or later]
* "GPL v2" [GNU Public License v2]
* "GPL and additional rights" [GNU Public License v2 rights and more]
* "Dual BSD/GPL" [GNU Public License v2
* or BSD license choice]
* "Dual MIT/GPL" [GNU Public License v2
* or MIT license choice]
* "Dual MPL/GPL" [GNU Public License v2
* or Mozilla license choice]
*
* The following other idents are available
*
* "Proprietary" [Non free products]
*
* There are dual licensed components, but when running with Linux it is the
* GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
* is a GPL combined work.
*
* This exists for several reasons
* 1. So modinfo can show license info for users wanting to vet their setup
* is free
* 2. So the community can ignore bug reports including proprietary modules
* 3. So vendors can do likewise based on their own policies
*/
Similarly, MODULE_DESCRIPTION() is used to describe what the module
does, MODULE_AUTHOR() declares the module's author, and
MODULE_SUPPORTED_DEVICE() declares what types of devices the module
supports.
These macros are all defined in linux/module.h and aren't used by the
kernel itself. They're simply for documentation and can be viewed by a
tool like objdump. As an exercise to the reader, try and search fo these
macros in linux/drivers to see how module authors use these macros to
document their modules.
I'd recommend to use something like *grep -inr MODULE_AUTHOR * * in
/usr/src/linux-2.6.x/ . People unfamiliar with command line tools will
probably like some web base solution, search for sites that offer kernel
trees that got indexed with LXR. (or setup it up on your local machine).
Users of traditional Unix editors, like *emacs * or *vi * will also find
tag files useful. They can be generated by *make tags * or *make TAGS *
in /usr/src/linux-2.6.x/ . Once you've got such a tagfile in your
kerneltree you can put the cursor on some function call and use some key
combination to directly jump to the definition function.
*Example 2-6. hello-4.c*
/*
* hello-4.c - Demonstrates module documentation.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#define DRIVER_AUTHOR "Peter Jay Salzman <[email protected]>"
#define DRIVER_DESC "A sample driver"
static int __init init_hello_4(void)
{
printk(KERN_INFO "Hello, world 4\n");
return 0;
}
static void __exit cleanup_hello_4(void)
{
printk(KERN_INFO "Goodbye, world 4\n");
}
module_init(init_hello_4);
module_exit(cleanup_hello_4);
/*
* You can use strings, like this:
*/
/*
* Get rid of taint message by declaring code as GPL.
*/
MODULE_LICENSE("GPL");
/*
* Or with defines, like this:
*/
MODULE_AUTHOR(DRIVER_AUTHOR); /* Who wrote this module? */
MODULE_DESCRIPTION(DRIVER_DESC); /* What does this module do */
/*
* This module uses /dev/testdevice. The MODULE_SUPPORTED_DEVICE macro might
* be used in the future to help automatic configuration of modules, but is
* currently unused other than for documentation purposes.
*/
MODULE_SUPPORTED_DEVICE("testdevice");
------------------------------------------------------------------------
2.6. Passing Command Line Arguments to a Module
Modules can take command line arguments, but not with the argc/argv you
might be used to.
To allow arguments to be passed to your module, declare the variables
that will take the values of the command line arguments as global and
then use the module_param() macro, (defined in linux/moduleparam.h) to
set the mechanism up. At runtime, insmod will fill the variables with
any command line arguments that are given, like *./insmod mymodule.ko
myvariable=5*. The variable declarations and macros should be placed at
the beginning of the module for clarity. The example code should clear
up my admittedly lousy explanation.
The module_param() macro takes 3 arguments: the name of the variable,
its type and permissions for the corresponding file in sysfs. Integer
types can be signed as usual or unsigned. If you'd like to use arrays of
integers or strings see module_param_array() and module_param_string().
int myint = 3;
module_param(myint, int, 0);
Arrays are supported too, but things are a bit different now than they
were in the 2.4. days. To keep track of the number of parameters you
need to pass a pointer to a count variable as third parameter. At your
option, you could also ignore the count and pass NULL instead. We show
both possibilities here:
int myintarray[2];
module_param_array(myintarray, int, NULL, 0); /* not interested in count */
int myshortarray[4];
int count;
module_parm_array(myshortarray, short, , 0); /* put count into "count" variable */
A good use for this is to have the module variable's default values set,
like an port or IO address. If the variables contain the default values,
then perform autodetection (explained elsewhere). Otherwise, keep the
current value. This will be made clear later on.
Lastly, there's a macro function, MODULE_PARM_DESC(), that is used to
document arguments that the module can take. It takes two parameters: a
variable name and a free form string describing that variable.
*Example 2-7. hello-5.c*
/*
* hello-5.c - Demonstrates command line argument passing to a module.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/stat.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Jay Salzman");
static short int myshort = 1;
static int myint = 420;
static long int mylong = 9999;
static char *mystring = "blah";
static int myintArray[2] = { -1, -1 };
static int arr_argc = 0;
/*
* module_param(foo, int, 0000)
* The first param is the parameters name
* The second param is it's data type
* The final argument is the permissions bits,
* for exposing parameters in sysfs (if non-zero) at a later stage.
*/
module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(myshort, "A short integer");
module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(myint, "An integer");
module_param(mylong, long, S_IRUSR);
MODULE_PARM_DESC(mylong, "A long integer");
module_param(mystring, charp, 0000);
MODULE_PARM_DESC(mystring, "A character string");
/*
* module_param_array(name, type, num, perm);
* The first param is the parameter's (in this case the array's) name
* The second param is the data type of the elements of the array
* The third argument is a pointer to the variable that will store the number
* of elements of the array initialized by the user at module loading time
* The fourth argument is the permission bits
*/
module_param_array(myintArray, int, &arr_argc, 0000);
MODULE_PARM_DESC(myintArray, "An array of integers");
static int __init hello_5_init(void)
{
int i;
printk(KERN_INFO "Hello, world 5\n=============\n");
printk(KERN_INFO "myshort is a short integer: %hd\n", myshort);
printk(KERN_INFO "myint is an integer: %d\n", myint);
printk(KERN_INFO "mylong is a long integer: %ld\n", mylong);
printk(KERN_INFO "mystring is a string: %s\n", mystring);
for (i = 0; i < (sizeof myintArray / sizeof (int)); i++)
{
printk(KERN_INFO "myintArray[%d] = %d\n", i, myintArray[i]);
}
printk(KERN_INFO "got %d arguments for myintArray.\n", arr_argc);
return 0;
}
static void __exit hello_5_exit(void)
{
printk(KERN_INFO "Goodbye, world 5\n");
}
module_init(hello_5_init);
module_exit(hello_5_exit);
I would recommend playing around with this code:
satan# insmod hello-5.ko mystring="bebop" mybyte=255 myintArray=-1
mybyte is an 8 bit integer: 255
myshort is a short integer: 1
myint is an integer: 20
mylong is a long integer: 9999
mystring is a string: bebop
myintArray is -1 and 420
satan# rmmod hello-5
Goodbye, world 5
satan# insmod hello-5.ko mystring="supercalifragilisticexpialidocious" \
> mybyte=256 myintArray=-1,-1
mybyte is an 8 bit integer: 0
myshort is a short integer: 1
myint is an integer: 20
mylong is a long integer: 9999
mystring is a string: supercalifragilisticexpialidocious
myintArray is -1 and -1
satan# rmmod hello-5
Goodbye, world 5
satan# insmod hello-5.ko mylong=hello
hello-5.o: invalid argument syntax for mylong: 'h'
------------------------------------------------------------------------
2.7. Modules Spanning Multiple Files
Sometimes it makes sense to divide a kernel module between several
source files.
Here's an example of such a kernel module.
*Example 2-8. start.c*
/*
* start.c - Illustration of multi filed modules
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
int init_module(void)
{
printk(KERN_INFO "Hello, world - this is the kernel speaking\n");
return 0;
}
The next file:
*Example 2-9. stop.c*
/*
* stop.c - Illustration of multi filed modules
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
void cleanup_module()
{
printk(KERN_INFO "Short is the life of a kernel module\n");
}
And finally, the makefile:
*Example 2-10. Makefile*
obj-m += hello-1.o
obj-m += hello-2.o
obj-m += hello-3.o
obj-m += hello-4.o
obj-m += hello-5.o
obj-m += startstop.o
startstop-objs := start.o stop.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
This is the complete makefile for all the examples we've seen so far.
The first five lines are nothing special, but for the last example we'll
need two lines. First we invent an object name for our combined module,
second we tell *make * what object files are part of that module.