linux device driver tutorial
The first driver:
loading and removing the driver in user space
nothing.c
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
Makefile
obj-m := nothing.o
compile and test:
$make -C /usr/src/linux-headers-3.16.7-ckt5my-very-own-kernel M=`pwd` modules
或者
make -C /lib/modules/`uname -r`/build M=`pwd` modules
out:
make: Entering directory `/usr/src/linux-lts-utopic-3.16.0'
CC [M] /home/wonfee/wonfee/linux/driver-tutorial/nothing/nothing.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/wonfee/wonfee/linux/driver-tutorial/nothing/nothing.mod.o
LD [M] /home/wonfee/wonfee/linux/driver-tutorial/nothing/nothing.ko
sudo insmod nothing.ko
lsmod |grep nothing
nothing 8255 0
sudo rmmod nothing
The “Hello world” driver:
loading and removing the driver in kernel space
hello.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_DEBUG "Hello World !!!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_DEBUG "Bye bye !!!\n");
}
module_init(hello_init);
module_exit(hello_exit);
make -C /usr/src/linux-headers-3.16.7-ckt5my-very-own-kernel M=`pwd` modules
make: Entering directory `/usr/src/linux-lts-utopic-3.16.0'
CC [M] /home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "mcount" [/home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.ko] undefined!
CC /home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.mod.o
LD [M] /home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.ko
make: Leaving directory `/usr/src/linux-lts-utopic-3.16.0'
sudo insmod hello.ko
insmod: ERROR: could not insert module hello.ko: Unknown symbol in module
dmesg |tail
...
[21684.565795] hello: Unknown symbol mcount (err 0)
加载内核模块出错,网上说是gcc 版本问题,当前使用的gcc是软链接到gcc-4.4,这是之前为了编译android源码时将gcc从4.8降到了4.4,重新将gcc链接到4.8:
gcc -v
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
make -C /usr/src/linux-headers-3.16.7-ckt5my-very-own-kernel/ M=`pwd` modules
make: Entering directory `/usr/src/linux-lts-utopic-3.16.0'
CC [M] /home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.mod.o
LD [M] /home/wonfee/wonfee/linux/driver-tutorial/helloworld/hello.ko
make: Leaving directory `/usr/src/linux-lts-utopic-3.16.0'
sudo insmod hello.ko
dmesg |tail -n 1
[22644.697688] Hello World !!!
sudo rmmod hello
dmesg |tail -n 1
[22663.379104] Bye bye !!!
Makefile
//------------ General Makefile------------------
obj-m := hello.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
编译模块,可以使用如下两种方式:
$make -C /usr/src/linux-xxx M=`pwd` modules
$make -C /lib/modules/uname -r
/build M=pwd
modules
两者效果相同, 只是使用的源码路径不一样,usr/src目录下那个源代码一般是我们自己下载后解压的或者系统更新时下载的,而lib目录下的则是在编译时自动copy过去的,两者其实是完全一样的。