这些天在学习linux内核编程,就在这里小小的show以下。
首先编写如下的linux代码。并命名为hello.c
这里你应该注意亮点:
第一、linux内核编程,不同于普通的用户态下的编程;有一个入口的main函数;这里的“main”函数是module_init();同时还有一个善后处理的函数:module_exit()。
第二、linux内核编程在编译的时候,不同于用户态下的编程;可以直接使用gcc编译器编译链接,就能够成为可执行的;而是需要编写一个Makefile文件,不是makefile!!这里牵扯到很多的内核态下的东西,具体的我也没弄清楚!详细的会在后面和大家分享。
hello.c 文件
- 1 #include <linux/module.h>
- 2 #include <linux/kernel.h>
- 3 #include <linux/init.h>
- 4 static int __init lkp_init(void);
- 5 static int __exit lkp_exit(void);
- 6
- 7
- 8 static int __init lkp_init(void)
- 9 {
- 10 printk("<1>Hello ,Word!\n");
- 11 return 0;
- 12 }
- 13
- 14 static int __exit lkp_exit(void)
- 15 {
- 16 printk("<2>Hello,Word exit\n");
- return 0;
- 17 }
- 18 module_init(lkp_init);
- 19 module_exit(lkp_exit);
并在hello.c的同一目录下建立Makefile文件。
Makefile文件:
- 1 ifneq ($(KERNELRELEASE),)
- 2 mymodule-objs:= hello.c
- 3 obj-m += hello.o
- 4
- 5 else
- 6 PWD :=$(shell
pwd) - 7 KVER := $(shell uname -r)
- 8 KDIR :=/lib/modules/$(KVER)/build
- 9
- 10 all:
- 11 $(MAKE) -C $(KDIR) M=$(PWD)
- 12 clean:
- 13 rm -rf *.o *.mod.c *.ko *.symvers *order *.markers *-
- 14 endif
说明:
当命令在执行make时,将调用Makefile文件。KERNELRELEASE 是在内核源代码的顶层/usr/src/linux-headers-2.6.32-33/Makefile 文件中定义的一个变量。读者如果下载的是linux-3.0的内核的话在**/linux-3.0/Makefile。当中的380行。如下:
- 379 # Read KERNELRELEASE from include/config/kernel.release (if it
exists) - 380 KERNELRELEASE = $(shell cat include/config/kernel.release
2> /dev/null) - 381 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL) ,.$(SUBLEVEL)))$(EXTRAVERSION)
在第一次读取执行此Makefile时,变量$(KERNELRELEASE) 并没有被设置,因此第一行ifneq的条件失败,从else后面的开始执行,设置PWD、KVER、KDIR等变量。
当make遇到标号all时,-C$(KDIR)指名跳转到内核源码目录下读取那里的Makefile。M=$(PWD),表明返回到当前的目录进行继续读入,执行当前的Makefile,也就是第二次调用make。这时的变量$(KERNELRELEASE)
已经被定义,因此ifneq成功,make将继续读取紧接在ifneq后面的内容。ifneq的内容为kbuild语句,指名模块源码中个文件之间的依赖关系和要生成的目标模块
语句 2 mymodule-objs:= hello.c
表是mymodule.o 由hello.c生成。 语句3 obj-m += hello.o表是链接后将生成mymodule.ko模块,这个文件就是要插入内核的模块文件。
如果make的目标是clean,直接执行clean标号之后的操作,删除 一大堆的东西!执行文clean后面的rm命令之后,make整个工作就结束了!
执行效果:
- [#35#[email protected]:~]$cd
kernel/ - [#36#[email protected]:~/kernel]$ls
- hello.c Makefile
- [#37#[email protected]:~/kernel]$make
- make -C /lib/modules/2.6.32-33-generic/build
M=/home/caopeng/kernel - make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.32-33-generic‘
- LD /home/caopeng/kernel/built-in.o
- CC [M] /home/caopeng/kernel/hello.o
- /home/caopeng/kernel/hello.c: In function ‘lkp_exit’:
- /home/caopeng/kernel/hello.c:17: warning: no
return statement in function returning non-void - /home/caopeng/kernel/hello.c: In function ‘__exittest’:
- /home/caopeng/kernel/hello.c:19: warning: return
from incompatible pointer type - Building modules, stage 2.
- MODPOST 1 modules
- CC /home/caopeng/kernel/hello.mod.o
- LD [M] /home/caopeng/kernel/hello.ko
- make[1]:正在离开目录 `/usr/src/linux-headers-2.6.32-33-generic‘
- [#38#[email protected]:~/kernel]$
编译成功!!
查看当前目录下的文件,会发现多了很多东西!如下:
- [#38#[email protected]:~/kernel]$ls
- built-in.o hello.ko
hello.mod.o Makefile Module.symvers - hello.c hello.mod.c
hello.o modules.order - [#39#[email protected]:~/kernel]$
这里不知道为什么生成的文件都没有x权限!这里要用到的就是hello.ko给其加上可执行权限。并使用insmod将其插入!然后用命令查看结果!
- [#47#[email protected]:~/kernel]$sudo
rmmod hello.ko - [#48#[email protected]:~/kernel]$sudo
insmod hello.ko - [#49#[email protected]:~/kernel]$dmesg -c
- klogctl: 不允许的操作
- [#50#[email protected]:~/kernel]$sudo
dmesg -c - [14651.331364] Hello,Word exit
- [14658.553284] Hello ,
- [#51#[email protected]:~/kernel]$
最后要记得rmmod!!!