driver book: chapter 2 building and running modules: Assignment: 1. get a linux kernel, 2.6.10 somehow downloaded/installed. 2. compile the kernel and make/install/reboot until you can run the new kernel. 3. make sure you can compile and load the code on p. 16. load with # insmod mymodule.ko unload with # rmmod mymodule.o list with #lsmod root@zymurgy:~ # uname -a Linux zymurgy 2.6.8.1-3-386 #1 Thu Nov 18 11:47:33 UTC 2004 i686 GNU/Linux [root@zymurgy root]# lsmod root@zymurgy:~ # lsmod | more Module Size Used by iptable_filter 3072 0 ip_tables 16896 1 iptable_filter r128 92708 2 proc_intf 3968 0 freq_table 4356 0 cpufreq_userspace 5336 0 cpufreq_powersave 2048 0 button 6936 0 ac 5132 0 af_packet 20872 0 battery 9740 0 ipv6 230020 18 3c59x 36776 0 e1000 75268 0 snd_intel8x0 33068 3 snd_ac97_codec 59268 1 snd_intel8x0 snd_pcm_oss 48168 0 snd_mixer_oss 16640 3 snd_pcm_oss snd_pcm 85540 2 snd_intel8x0,snd_pcm_oss snd_timer 23172 1 snd_pcm snd_page_alloc 11144 2 snd_intel8x0,snd_pcm gameport 4736 1 snd_intel8x0 snd_mpu401_uart 7296 1 snd_intel8x0 snd_rawmidi 23232 1 snd_mpu401_uart snd_seq_device 7944 1 snd_rawmidi and more! Note high-level kernel functionality in terms of module loading at boot depends on linux system in toto packaging, debian, fedora, slackware, joebob'sausageandlinuxdistro, whatever. That said ... SEE ALSO insmod(8), modprobe(8), rmmod(8), ksyms(8) See dmesg for errors. modprobe/depmod/ksyms are higher-level system for organizing modules and their symbol dependencies printk - used as printf in the linux kernel. string roughly has priority/string. High priorities go with low numbers. Chapter 4 has more details. YOU WANT TO READ CHAPTER 4. Note that messages are logged and will appear in /var/log/messages. --------------------------------- kernel modules versus applications: module main terminates immediately. module registers itself so that kernel is linked to it. modules are event driven (driven by some other actor elsewhere, interrupt or top-half system-call) apps can call functions they did not define (printk) TBD: find printk code in kernel. See Figure 2.1: ONLY FUNCTIONS THAT ARE PART OF KERNEL CAN BE CALLED IN MODULES. not library code in libc. kernel includes found in /usr/include/linux and /usr/include/asm inside the kernel sources that you are actually using. (which may be relative in terms of filepath, and not actually /usr/include anything. It is nice if /usr/include matches the kernel you are using though). #ifdef __KERNEL__ used for kernel code, not app code when headers are shared namespace pollution -- too many symbols actually used in a blob of code ... therefore defensive programming technique only declare names to be external when actually needed; i.e., static int x; better than int x; also note: kernel segmentation faults can lead to 1. a reboot or 2. a damaged hard disk. This is why ext3, reiserfs, etc ... logging fs are good for kernel development. User space/kernel space modules run in kernel space. user apps run in user space. Remember there are 2 hw-enforced execution modes, 1. supervisor, and 2. user. kernel code executes in context of supervisor virtual memory addressing AND supervisor mode. user processes execute in user mode and in their own user virtual MMU addressing context. module (assume it is a driver) executes in kernel space driver by user-mode system calls may respond to hw interrupts as well concurrency in the kernel top-half vs bottom-half rant must be issued at this point. Note single-cpu vs SMP problem ... result is need for classic sequential access mechanisms, semaphores, spin loops, event queues, etc. class single-cpu UNIX is: non-preemptive in kernel mode. single-cpu multiple user processes give concurrency traditional UNIX pov: only one user process executes in top-half but: in 2.6 kernel code is all preemptive ... so even single CPU top-half must be written in preemptive manner. chapter 5 has details. still have race conditions between interrupt drivers and top-half of kernel or interrupt-drivers and other interrupt-drivers SMP kernel TH vs BH all can run in parallel must code for SMP at this point. linux code must be reentrant keep threads whether from system call or interrupt separate cannot race on variable access the current process global "current" is pointer to struct task_struct which is declared really in defined by linux/sched.h process TCB at least distinguishes one process from another current is not simple under SMP but apparently the semantics have not changed (for presumably simple uses) current->pid for pid current->comm for name of executable kernel stack is small, use kernel malloc or some variant for structures. __foo() is low-level component and should be called with care no floating point (use fixed point if necessary) compiling and loading must have a built kernel on system for modules. look at gnu Makefile on p.23/p. 24 can build kernel modules outside of kernel sub-directory two-level make incantation skull - test module mentioned in book can steal code/Makefile as template note -r used for ld ..., means generate .o file that can be used as input to ld to generate another .o file, not "final" exec file. module handling code in kernel/module.c system call for this is sys_create_module() -> sys as prefix means system call for a function *************************************************** sys_init_module allocates space for module with vmalloc modprobe vs insmod modprobe discovers that functions/names are not defined, and tries to find other .ko's in path to load to resolve dependencies insmod just fails with unresolved dependency lsmod lists modules - reads /proc/modules version dependency serious module con: ... mismatched module with kernel can lead to kernel panic because of possible namespace conflicts, and for reasons of general sanity, your module MAY be compiled under the o.s. includes ... and with the installed os as well. does this for you module is linked against vermagic.o module insmod -f can be used to override this problem but this may be a bad idea. insmod also uses version-dependent path when asked to load an object file (that you didn't have in the current directory) /lib/modules/build_version See p. 27. for version macros make install puts drivers in /lib/modules/$(VERSION)/something Platform Dependency you may push the envelope here ... more so that app developers. trade-off is loss of platform independence code may be compiled for processor-specific features, thus the compatibility of a .ko object may lead to a KO elsewhere. best to try to get src into kernel Kernel symbol table module has access to functions and global variables in kernel if you officially export a symbol it becomes part of kernel symbol table public symbol table can be read from /proc/ksyms or via output of ksyms command note: # ksyms -a module stacking may occur (think of it as class and sub-class) e.g., msdos fs uses fat symbols modprobe exists to load modules needed by other modules. EXPORT_SYMBOL(s); EXPORT_SYMBOL_GPL(s); - must be GPL licensed module Preliminaries #include - basic module init stuff #include - init/cleanup functions See p. 30 for other stuff Initialization and Shutdown note: certain kinds of general kernel facilities may be registered and in general should be removed when the module is uninstalled. E.g., /proc/file is registered in order to allow kernel/app communication. or registering a net device (driver) or about 1 million other things more /proc/ksyms | grep register see top of p.31 for simple init function registration note __init means function is dropped after being run registration functions start with register_ cleanup function unregister return resources (interrupts/malloc'ed memory) see code p. 32, note __exit error handling in init_module if init_module fails you must back out of any kernel facilities you are using free memory See p.33 for an example. init_module returns an ERROR code. It should be meaningful see linux/errno.h, negative number error codes For example, if not enough memory, return -ENOMEM. another approach: p.34 a cleanup function, call it upon failure module loading races make sure you prepare whatever you need for registration BEFORE you register something module params insmod/modprobe can assign params the latter has params in /etc/modprobe.conf insmod hellop howmany=10 whom="Mom" see p. 36 user space programming might choose to write program or at least rough cut version in user space doit thru user ports pros: 1. can use libc 2. can use a conventional debugger like gdb 3. if it hangs, you kill it. if you loop in the kernel ... what happens? 4. memory is "more" virtual, swappable, easier to use Example: X server but it has memory mapped access to controller memory. other procs use TCP to talk to it. cons: 1. no interrupts 2. context switch latency 3. kernel as vast sea of shared functions not available 4. no dma