linux device driver学习——day1编写自己的模块

学习目的

搭建驱动开发的环境,能够编译自己的模块

预备知识

如何编译自己的模块

1. 下载对应版本linux源码树,用于构建模块

2. 编写自己模块的makefile

需要了解的是linux的kbuild系统,这里简单介绍一下模块的makefile的通用写法

/* Makefile:单个源文件编译的模块 */
obj-m := hello.o

/* Makefile:多个源文件编译的模块 */
obj-m := module.o
module-objs := file1.o file2.o

/* shell 环境:编译指令 */
make -C /usr/src/linux-source-4.15.0 M=`pwd` modules   //-C表示在make被执行的时候先进入/usr/src/linux-source-4.15.0目录执行顶层的Makefile,M表示在编译模块之前返回到当前目录

上面的方法比较麻烦,一般在自己编写驱动模块的时候会使用下面这种通用的Makefile,直接执行make就可以编译自己的模块了

/* 利用KERNELRELEASE变量 */
ifneq ($(KERNELRELEASE),)
        obj-m := hello.o
else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)
default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif

必须的要素

头文件

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

这两个头文件包含了模块编写时所需的一些必要的符号定义

许可

MODULE_LICENSE("GPL");

各个许可的含义在网上可以找到

错误处理

在内核空间中,注册的操作可能会失败,所以需要一直检查返回值,在发生错误之后,必须要清理错误,释放资源。

使用的错误码在<linux/errno.h>中定义,注意引用该文件

下面有两种方法:

  1. 初始化的每一步发生错误使用goto语句跳转到对应的错误处理语句,原则是先分配的后释放,后分配的线释放。

这种方式写的代码,结构对称,有分配就有相应的错误处理,但是代码里面重复的部分就很多。

例子如下:

int __init my_init_function()
{
    int err;
    err = register_this(ptr1, "scull");
    if (err)
            goto fail_this;
    err = register_that(ptr2, "scull");
    if (err)
            goto fail_that;
    err = register_those(ptr3, "scull");
    if (err)
            goto fail_those;
fail_those:
    unregister_that(ptr3, "scull");
fail_that:
    unregister_this(ptr1, "scull");
fail_this:
    return err;
}
  1. 为了解决分配操作多的时候带来的goto语句过多的问题,我们可以把处理语句封装在一个处理函数中.

例子如下:

struct something *item1;
struct somethingelse *item2;
int stuff_ok;

void my_cleanup()
{
    if (item1)
            release_thing1(item1);
    if (item2)
            release_thing2(item2);
    if (stuff_ok)
            unregister_stuff();
    return;
}

int __init my_init(void) {
    int err = -ENOMEM;
    item1 = allocate_thing(arguments);
    item2 = allocate_thing2(arguments2);
    if (!item2 || !item2)
            goto fail;
    err = register_stuff(item1, item2);
    if (!err)
            stuff_ok = 1;
    else
            goto fail;
    return 0; /* success */ 
fail:         
    my_cleanup();
    return err;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值