《LINUX设备驱动》学习总结(基础篇)

基本概念:

编程机制和策: “需要提供什么样的功能(机制)”和“如何使用这些功能(策略)”
编写驱动程序应注意:编写访问硬件的内核代码时,不要给用户强加任何策略。不过有时候还是需要实现一些策略,例如,某个数字IO驱动程序只提供以字节为单位访问硬件的方法,这样可以避免写额外代码来处理单个数据位的麻烦。

内核模块和应用程序: 理解module_init 和module_exit 。模块初始化的任务是为以后调用模块函数做预先准备; 模块退出函数是为了告诉内核“我要离开了不要再让我做任何事了”。 应用程序退出时可以不管资源的释放或者其他清理工作,但是,模块退出函数必须要仔细撤销初始化函数所做的一切,否则,在系统重新引导之前某些东西就会残留在系统中。
应用程序能够调用它并未定义的函数,这是因为链接过程能够解析外部引用从而使用适当的函数库。例如定义在libc中的printf函数就是这种可被调用的函数之一。然而,模块仅仅被链接到内核,因此它能调用的函数仅仅是由内核导出的那些函数,而不存在任何可链接的函数库。
因为没有任何函数库和模块链接,因此,源文件中不能包含通常的头文件,像

# To build modules outside of the kernel tree, we run "make"
# in the kernel source tree; the Makefile these then includes this
# Makefile once again.
# This conditional selects whether we are being included from the
# kernel Makefile or not.
ifeq ($(KERNELRELEASE),)  #判断是否被上层makefile包含,区别在单独编译和与内核一起编译。

    # Assume the source tree is where the running kernel was built
    # You should set KERNELDIR in the environment if it's elsewhere
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build  #指定内核路径,需要是目录中包含.config文件,即配置好的内核
    # The current directory is passed to sub-makes as argument
    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

.PHONY: modules modules_install clean

else
    # called from kernel build system: just declare what our modules are
    obj-m := hello.o

endif

makefile基础
赋值符号 “=” “:=” “?=” “+=”
= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值 两个链接符之间用自动添加空格

关于 := 和 = 的区别看下面的例子

            A=first
            B:=$(A)add
            A=final
all:
            @echo $(B)

运行 make 结果显示 firstadd

        A=first
        B=$(A)add
        A=final
all:
        @echo $(B)

运行make显示 finaladd

总结:似乎 使用:=赋值的时候没有对后面的赋值语句进行检查,而使用 =的时候会受到后面语句的影响。
语句中@echo 和echo的区别是是否显示echo 。加@echo只显示输出结果不显示命令。echo会显示命令之后显示对应输出。

“ifdef”是条件关键字。语法是ifdef ;; else ; endif
ifdef只检验一个变量是否被赋值,它并不会去推导这个变量,并不会把变量扩展到当前位置。
“ifeq”与“ifdef”类似。“ifeq”语法是ifeq (;, ;),功能是比较参数“arg1”和“arg2”的值是否相同。

ifneq ($(KERNELRELEASE),)
     module-objs:=hello.o  #当有多个源文件时可以写成  hello1.o hello2.o
     obj-m:=hello.o   #有多个源文件时这个名字不能和上面的重复
else
    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
endif

clean:
        rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean   

学习中遇到问题:
1、printk输出数据没在终端显示
重新打开一个终端,在终端下输入

    whlie true
    do
        sudo dmesg -c
        sleep   1
    done

这段程序会不停的读取当前系统日志并清空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值