本文共 2781 字,大约阅读时间需要 9 分钟。
驱动程序应该处理如何使硬件可用、而将怎样使用硬件留给上层应用程序。设备分类:字符设备、块设备、网络设备。 字符设备驱动程序至少实现open、close、read、write系统调用。字符设备可以通过文件系统节点来访问。这些设备文件和普通文件之间的唯一差别在于普通文件的访问可以前后移动访问位置,而大多字符设备是一个只能顺序访问的数据通道。 块设备上能容纳文件系统,一个文件系统决定了如何在块设备上组织数据,以及表示目录和文件形成的树。文件系统不是设备驱动程序,它没有实际物理设备同这种信息组织方式相关联。它只是个软件驱动程序,将低层数据结构映射到高层数据结构。 模块能调用的函数仅仅是由内核导出的那些函数,而不存在任何可连接的库函数。Linux内核代码必须是可重入的,它必须能同时运行在多个上下文。
#include#include MODULE_LICENSE("Dual BSD/GPL");static int hello_init(void){ printk(KERN_ALERT "Hello, world\n"); return 0;}static void hello_exit(void){ printk(KERN_ALERT "Goodbye, world\n");}module_init(hello_init);module_exit(hello_exit);
方法一、Makefile+命令行
Makefileobj-m := hello.o
命令行
make -C /usr/src/linux-headers-4.13.0-16-generic M=`pwd` modules//这里4.13.0-16-generic=uname -r
方法二、完整的Makefile
obj-m := hello.o KERNELBUILD := /lib/modules/$(shell uname -r)/builddefaule: make -C $(KERNELBUILD) M=$(shell pwd) modulesclean: rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers
make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行。KERNELRELEASE定义在内核Makefile中,所以执行else后面的KERNELDIE, PWD赋值,执行default:-C指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被定义,**kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。**else之前的内容为kbuild语法的语句,指明模块源码中各文件的依赖关系,以及要生成的目标模块名
# Comment/uncomment the following line to disable/enable debugging#DEBUG = y# Add your debugging flag (or not) to CFLAGSifeq ($(DEBUG),y) DEBFLAGS = -O -g # "-O" is needed to expand inlineselse DEBFLAGS = -O2endifEXTRA_CFLAGS += $(DEBFLAGS) -I$(LDDINCDIR)ifneq ($(KERNELRELEASE),)# call from kernel build systemobj-m := hello.oelseKERNELDIR ?= /lib/modules/$(shell uname -r)/buildPWD := $(shell pwd)default: $(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINCDIR=$(PWD)/../include modulesendifclean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions//make depend = make .depend = make depdepend .depend dep: $(CC) $(EXTRA_CFLAGS) -M *.c > .dependifeq (.depend,$(wildcard .depend))include .dependendif
转载地址:http://wcujn.baihongyu.com/