跳转至

驱动开发简介

简介

本文及该系列的后续文章主要用于记录在学习Linux驱动开发过程中的相关总结或者是备忘,可能现阶段无法保证所有的理解完全正确, 后续会根据实际的学习进度来来时刻更新该系列的内容。

什么是Linux驱动?

Linux驱动是运行的Linux内核里面的软件模块,它负责让Linux能够识别和控制相应的硬件模块,同时让用户控件的代码可以安全,方便的访问这些硬件。

为什么需要驱动程序?

硬件的设备种类很多,他们的控制方式,通信协议,寄存器地址都各不相同,操作系统无法自动自动如何控制这些硬件,所以需要驱动程序来告诉操作系统,同时驱动程序也提供了一个统一的接口,让用户可以使用统一的接口操作不同的硬件设备。

           系统调用
用户程序 ------------> Linux内核(->驱动程序) ---> 硬件设备

存在两种不同形式的Linux驱动变成方案:

  • 将驱动和内核一起编译,每次修改代码需要将内核和驱动都重新编译一次
  • 已内核模块的形式实现驱动,Linux可以加载或者卸载该模块,不需要编译内核

本文将讨论第二种形式。

创建一个内核模块

创建一个文件: mydriver.c,并添加以下代码:

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kern");
MODULE_DESCRIPTION("Our first kernel module");

static int my_init(void)
{
    return 0;
}

static void my_exit(void)
{
    return;
}

module_init(my_init);
module_exit(my_exit);
  • 通过module_init定义加载module的时候调用的函数
  • 通过module_exit定义卸载module的时候调用的函数

这是最简单的一个内核模块,当前目前没有任何功能。我们先创建一个Makefile,来保证上述的模块可以正常编译

TARGET_MODULE := test_module
$(TARGET_MODULE)-objs := mydriver.o
obj-m += $(TARGET_MODULE).o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
load:
    insmod ./$(TARGET_MODULE).ko
unload:
    rmmod ./$(TARGET_MODULE).ko

运行make命令,检查输出,最终我们可以看到一个test_module.ko文件,这即使后续我们需要加载的内核模块。

小试牛刀

上述代码没有任何功能,我们先对上述代码做一点优化,在模块加载以及卸载的时候,打印一些日志出来

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kern");
MODULE_DESCRIPTION("Our first kernel module");

static int my_init(void)
{
    printk("I have insert the first module\n");
    return 0;
}

static void my_exit(void)
{
    printk("My first module has been removed");
    return;
}

module_init(my_init);
module_exit(my_exit);

注意: 这里我们增加了两个printk函数,用于打印相关的测试日志

重新运行make语句,生成新的test_module.ko文件。

make

  • 插入模块
sudo insmod ./test_module.ko

运行上述命令将我们编写的第一个模块插入到内核中运行

insmod

我们通过echo $?检查了以下返回值,看起来模块加入没有问题。

然后我们运行dmesg命令,来打印kernl ring buffer里的内容,这里能够看到模块相关的加载信息。

dmesg output

观察最后一行的输出内容,这里我们在my_init函数里面打印出来的日志,说明内核已经成功的加载并运行了我们写实现的 模块。

运行"cat /proc/modules"命令,/proc/modules是linux系统中的一个虚拟文件,用于显示已经加载到内核中的所有模块 (.ko驱动文件),包括他们的名字,大小,引用技术和以来关系。

procmodule

试一试从里面能不能找到我们自己系的模块。