linux简单驱动hello world内核模块
hello.c
#include<linux/module.h> #include<linux/init.h> #include<linux/fs.h> #include<linux/miscdevice.h> int hello_init(void) { // printk(KERN_EMERG"printk level:%s hello world!\n",KERN_EMERG); printk(KERN_ALERT"printk level:%s hello world!\n",KERN_ALERT); printk(KERN_CRIT"printk level:%s hello world!\n",KERN_CRIT); printk(KERN_ERR"printk level:%s hello world!\n",KERN_ERR); printk(KERN_WARNING"printk level:%s hello world!\n",KERN_WARNING); printk(KERN_NOTICE"printk level:%s hello world!\n",KERN_NOTICE); printk(KERN_INFO"printk level:%s hello world!\n",KERN_INFO); printk(KERN_DEBUG"printk level:%s hello world!\n",KERN_DEBUG); return 0; } void hello_exit(void) { printk(KERN_EMERG"printk level:%s goodbye world!\n",KERN_EMERG); printk(KERN_ALERT"printk level:%s goodbye world!\n",KERN_ALERT); printk(KERN_CRIT"printk level:%s goodbye world!\n",KERN_CRIT); printk(KERN_ERR"printk level:%s goodbye world!\n",KERN_ERR); printk(KERN_WARNING"printk level:%s goodbye world!\n",KERN_WARNING); printk(KERN_NOTICE"printk level:%s goodbye world!\n",KERN_NOTICE); printk(KERN_INFO"printk level:%s goodbye world!\n",KERN_INFO); printk(KERN_DEBUG"printk level:%s goodbye world!\n",KERN_DEBUG); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); //MODULE_ALTHOR("YXD"); //MODULE_DESCRIPTION("A simple module");
Makefile1
#Makefile ifneq ($(KERNELRELEASE),) obj-m :=hello.o #KERNELDIR:=/opt/FriendlyARM/mini2440/linux-2.6.32.2 else PWD:=$(shell pwd) modules: $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules #modules_install: # $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions endif #all: # make -C /opt/FriendlyARM/mini2440/linux-2.6.32.2/build SUBDIRS=$(PWD) modules #clean: # make -C /opt/FriendlyARM/mini2440/linux-2.6.32.2/build SUBDIRS=$(PWD) clean
注:Makefile1是基于x86平台的;其中uname -r是shell指令,可以在cmd窗口使用uname -r,便可以了解该指令的目的
Makefile1在make时,可能会出现报错
make: *** /lib/modules/***(uname -r检索到的内容)/build: No such file or directory. Stop.
错误显示 没有 /lib/modules/***/build 这个目录;可以到所指示的路径下,查看有没有build,没有的话安装kernel-devel, kernel-headers软件包
Makefile2
#Makefile #ifneq ($(KERNELRELEASE),) obj-m :=hello.o KERNELDIR:=/opt/FriendlyARM/mini2440/linux-2.6.32.2 #else PWD:=$(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions #endif #all: # make -C /opt/FriendlyARM/mini2440/linux-2.6.32.2/build SUBDIRS=$(PWD) modules #clean: # make -C /opt/FriendlyARM/mini2440/linux-2.6.32.2/build SUBDIRS=$(PWD) clean
而Makefile2是下载了一个新的内核;
KERNELDIR是指示头文件所在的路径,实际上hello.c中用到的module.h, init.h, fs.h在 /opt/FriendlyARM/mini2440/linux-2.6.32.2/include/linux中,但指示的路径只是到 /opt/FriendlyARM/mini2440/linux-2.6.32.2
估计是因为linux下makefile,它会指引着编译器找到相应的头文件
用make编译成功后,insmod hello.ko可能会出现Invalid module format 错误:
内核无法加载模块的原因是因为记载版本号的字符串和当前正在运行的内核模块的不一样,这个版本印戳作为一个静态的字符串存在于内核模块中,叫vermagic,通过指令modinfo hello.ko可以看到
注意:这里的hello.ko是基于我们下载的内核linux-2.6.32.2, 而我的虚拟机,当前正在运行的内核是fedora9.0,两者的版本号不符。