linux驱动学习加强版-1 (基本知识补充)

文章介绍了Linux驱动开发中的Makefile文件的使用,包括内核版本(KEVN)的获取、当前路径(PWD)和内核目录(KERN_DIR)的定义。在驱动框架部分,讲解了驱动的入口和出口函数。在编译多个KO模块时,指出了使用:=会导致上一次的设置被覆盖,应使用+=来追加多个模块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


虽然现在已经在Linux底层驱动工程师的路上走了一年多,但是很多细节应为工作中没有遇到过,所以也没有去了解过详细的原因,但是最近发现一些基础还是很重要的,所以现在开始弥补一些东西,经可能的详细的去说明一些东西。
后续也打算将这一些系列更新下去

先看这篇

这篇文章是我之前学习的一个文章,后续的将会在这个基础上进行
上次的Makefile文件也在这里补充说明一下:

一、Makefile文件说明

代码:

KEVN := $(shell uname -r)
PWD  := $(shell pwd)
KERN_DIR := /lib/modules/$(KEVN)/build

obj-m := hello.o

all:
        make    -C $(KERN_DIR) M=$(PWD) modules
clean:
        make    -C $(KERN_DIR) M=$(PWD) clean

上面就是一个简单的

KEVN := $(shell uname -r)

KEVN代表的是内核版本,这只是一个名字,随便你改。
$(shell uname -r) 就相当于你的 shell下执行了 一次 uname -r 的命令,执行这个命令就是查看你当前PC的内核版本
在这里插入图片描述

PWD  := $(shell pwd)

PWD代表就是当前的代码路径,一个名字和 KEVN一样的意思
$(shell pwd) 这个就是一个执行命令而已

KERN_DIR := /lib/modules/$(KEVN)/build

KERN_DIR 代表的是你内核编译需要的目录,同样的名字这些可以随便修改。

/lib/modules/$(KEVN)/build

后面就是ubuntu系统中的一些库了 ,其中包含我们的头文件。
不然没办法编译过。

二、驱动框架

先看驱动源码

#include <linux/module.h>
#include <linux/init.h>

static int hello_init(void) {
	printk(KERN_DEBUG "hello world\n");
	return 0;
}

static void hello_exit(void) {
	printk(KERN_DEBUG"goodbye my world\n");
}

module_init(hello_init); 
module_exit(hello_exit);

MODULE_LICENSE     ("GPL");
MODULE_AUTHOR      ("XHH");
MODULE_DESCRIPTION ("A test module");

驱动的入口函数

module_init(hello_init);
// 这里去调用的hello_init函数

驱动的出口函数

module_exit(hello_exit);

驱动的出口函数

需要注意的是,入口函数是Int类型有返回值
出口函数是void类型,是没有返回值的

再android的内核中,即使我们的入口函数和出口函数名字是一样的,我们也可以成功的编译,原因是内核做好了工作,每个驱动module_init的时候,都会有自己的属性,属于是独一无二,即使的你名字是重名的,也不影响,就好像你会遇到一个和你重名的人,但是你遇不到一个和你同一个身份证号的人。
但是为了规范,我们也一般不会去报驱动名字弄成一样的。

三、编译多个ko模块

KEVN := $(shell uname -r)
PWD  := $(shell pwd)
KERN_DIR := /lib/modules/$(KEVN)/build

obj-m := hello.o

all:
        make    -C $(KERN_DIR) M=$(PWD) modules
clean:
        make    -C $(KERN_DIR) M=$(PWD) clean

这里其实是有问题的,问题就在

obj-m := hello.o

这里,没错,单独编译一个驱动是没有问题的。但是如果你继续添加一个驱动呢
比如我再添加一个驱动,

KEVN := $(shell uname -r)
PWD  := $(shell pwd)
KERN_DIR := /lib/modules/$(KEVN)/build

obj-m := hello.o
obj-m := hello_world.o


all:
        make    -C $(KERN_DIR) M=$(PWD) modules
clean:
        make    -C $(KERN_DIR) M=$(PWD) clean

你会发现只编译了hello_wrold这个模块,你的hell.ko模块没有编译出来。
当你互换两个顺序的时候

obj-m := hello_world.o
obj-m := hello.o

你会发现只编译了hello.ko,宾没有编译hello_world的模块。这是为啥呢,因为
:= 这个符号的原因。
如果我们需要编译多个ko那么就需要将这个:= 改为 +=
因为 := 是覆盖之前的值 += 是继续添加值。
可以理解为我 := 这个算法我之看最后一次的,之前赋予的值会被覆盖掉,所以我们在Makefile里面添加多少个驱动,只有最后一个会生效。

所以我们要编译多个驱动只需要将 := 改为 += 就可以了

一般来说这是内核给你做好了的,
在这里插入图片描述
内核里面都是用的+= 所以一般我们也不会注意这个问题,这里提出来说一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永不秃头的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值