Overview
1. The role of the device driver
User activities are performed by means of a set of standardized calls that areindependent of the specific driver;mapping thosecalls to device-specific operations that act on real hardware isthen the role of the device driver.
Therole of a device driver is providing mechanism, not policy.
2. Mechanism vs. Policy
Mechanism:what capabilities are to be provided
Policy:how those capabilities can be used"
If the two issues are addressed by different parts of the program, or even bydifferent programs altogether, the software package is much easier to developand to adapt to particular needs.
3. Kernel architecture
4. Classes of Devices and Modules
TheLinux way of looking at devices distinguishes between three fundamentaldevice types. Each module usually implements one of these types, and thus isclassifiable asa char module, a block module, or a networkmodule.
Characterdevices: A character (char) device is one that canbe accessed as a stream of bytes (like a file); a char driver is in charge of implementing thisbehavior.
Blockdevices: A block device is a device (e.g., a disk) that can host a filesystem.In most Unix systems, a block device can only handle I/O operations thattransfer one or more whole blocks, which are usually 512 bytes (or a largerpower of two) bytes in length.
Networkinterfaces: Any network transaction is made through an interface, that is, adevice that is able to exchange data with other hosts.
Hello, World
1. Set up your test system
Ubunto8.10 + Skyeye
http://code.google.com/p/ldd6410/wiki/SkyeyeInLdd6410
2. Source codes (Using Linux-2.6.31)
hello.c
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT"Hello, world\n");
return0;
}
static void hello_exit(void)
{
printk(KERN_ALERT"Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
PWD := $(shell pwd)
KERNELDIR =/home/bambreeze/workspace/ldd6410-read-only/linux-2.6.31
INSTALLDIR =/home/bambreeze/workspace/skyeye/initrd/lib/modules
CROSS_COMPILE = arm-linux-
CC = $(CROSS_COMPILE)gcc
obj-m := hello.o
.PHONY: modules modules_install clean
modules:
$(MAKE)-C $(KERNELDIR) M=$(PWD) modules
modules_install:
cphello.ko $(INSTALLDIR)
clean:
rm-rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.orderModule.symvers
3. Build
(1) Prepare for the Root File System –initrd.img
$ sudo mount -o loop initrd.img initrd
(2) Build Linux kernel image - vmlinux
$make vmlinux
$cp vmlinux /var/lib/tftpboot/
$cp vmlinux ~/workspace/skyeye/
(3) Build module - hello.ko
$make modules
$ sudo make modules_install(4) Build the Root File System – initrd.img
$sudo umount initrd
4. Run
We have two methods to run Skyeye with Linux.
(1) Boot up vmlinux image directly
$sudo skyeye -e vmlinux -cskyeye-standalone.conf
(2) Boot up u-boot firstly, then tftpdownload and boot up vmlinux image in the u-boot finally
$sudoskyeye -e u-boot -cskyeye-with-uboot.conf -l 0x30000000,0xFFFFFF
…
SMDK2410 # tftp 0xc0000000 vmlinux
TFTP from server 10.0.0.1; our IP addressis 10.0.0.2
Filename 'vmlinux'.
Load address: 0xc0000000
Loading:#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#############################################
done
Bytes transferred = 3889865 (3b5ac9 hex)
SMDK2410 # bootelf 0xc0000000
Loading .text.head @ 0xc0008000 (992 bytes)
Loading .init @ 0xc00083e0 (142368 bytes)
Loading .text @ 0xc002b000 (2336392 bytes)
Loading __ksymtab @ 0xc0266000 (18704bytes)
Loading __ksymtab_gpl @ 0xc026a910 (7160bytes)
Loading __ksymtab_strings @ 0xc026c508(55521 bytes)
Loading __param @ 0xc0279dec (4628 bytes)
Loading .ARM.unwind_idx @ 0xc027b000 (80448bytes)
Loading .ARM.unwind_tab @ 0xc028ea40 (2424bytes)
Loading .data @ 0xc0290000 (117632 bytes)
Clearing .bss @ 0xc02acb80 (140392 bytes)
## Starting application at 0xc0008000 ...
Linux version 2.6.31.6-svn79(bambreeze@bambreeze-laptop) (gcc version 4.2.2) #9 Fri May 27 10:32:44 CST2011
CPU: ARM920T [41009200] revision 0(ARMvundefined/unknown), cr=00003177
…
5. Test the modules
# pwd
/lib/modules
# insmod hello.ko
Hello, world
# lsmod
Not tainted
hello 1088 0 - Live 0xc1128000
# rmmod hello
Goodbye, cruel world
# lsmod
Not tainted
6. Debug
Char Drivers (scull)
1. Source codes
scull.c
scull_tests.c
Makefile
PWD := $(shell pwd)
KERNELDIR =/home/bambreeze/workspace/ldd6410-read-only/linux-2.6.31
INSTALLDIR =/home/bambreeze/workspace/skyeye/initrd/lib/modules
CROSS_COMPILE = arm-linux-
CC = $(CROSS_COMPILE)gcc
# Comment/uncomment the following line todisable/enable debugging
#DEBUG = y
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expandinlines
else
DEBFLAGS = -O2
endif
#CFLAGS += $(DEBFLAGS)
#CFLAGS += -I$(LDDINC)
#EXTRA_CFLAGS += $(DEBFLAGS) -I$(LDDINC)
# call from kernel build system
ifneq ($(KERNELRELEASE),)
#scull-objs := main.o pipe.o access.o
obj-m :=scull.o
else
modules:
$(MAKE)-C $(KERNELDIR) M=$(PWD) modules
endif
modules_tests: scull_tests.o
$(CC)-o scull_tests scull_tests.o
modules_install:
mount-o loop /home/bambreeze/workspace/skyeye/initrd.img/home/bambreeze/workspace/skyeye/initrd/
cpscull.ko $(INSTALLDIR)
cpscull_tests $(INSTALLDIR)
umount/home/bambreeze/workspace/skyeye/initrd/
clean:
rm-rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.markersmodules.order Module.symvers scull_tests
depend .depend dep:
$(CC)$(CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
.PHONY: modules modules_testsmodules_install clean
2. Build
$make modules
$ sudo make modules_install3. Test & Verify
$sudo skyeye -e vmlinux -cskyeye-standalone.conf
…
# cd lib/modules
# ls -l
drwxr-xr-x 3 root root 1024 Jan 16 2010 2.6.31.6-svn79
-rw-r--r-- 1 root root 2244 May 27 2011 hello.ko
-rw-r--r-- 1 root root 9027 May 27 2011 scull.ko
-rwxr-xr-x 1 root root 9688 May 27 2011 scull_tests
# insmod scull.ko
# cat /proc/devices | grep scull
254 scull
# mknod -m 666 /dev/scull0c 254 0
# ./scull_tests
write ok! code=20
read ok! code=20
[0]=0 [1]=1 [2]=2 [3]=3 [4]=4
[5]=5 [6]=6 [7]=7 [8]=8 [9]=9
[10]=10 [11]=11 [12]=12 [13]=13 [14]=14
[15]=15 [16]=16 [17]=17 [18]=18 [19]=19
参考文献
1. Linux Device Drivers, Third Edition [LWN.net]
2. Linux Device Drivers (example fix)