• Linux驱动开发入门 demo


    驱动开发时候,尽量选择对应操作系统内核的Linux系统作为上位机平台

    下载源码与编译

    源码的下载可以从网站:https://mirrors.edge.kernel.org/pub/linux/kernel/

    找到对应的内核版本,然后下载,通过make menuconfig和make,进行编译。

    没有编译过的内核,驱动开发过程中进行编译可能有错误,找不到文件等。

    编写一个最简单的驱动

    如下是hello.c文件的驱动程序。其中声明了证书,和模块加载后与退出时应该执行的函数。

    #include<linux/module.h>
    #include<linux/kernel.h>
    MODULE_LICENSE("Dual BSD/GPL");
    static int hello_init(void)
    {
            printk(KERN_ALERT "hello,world
    ");
            return 0;
    }
    static void hello_exit(void)
    {
            printk(KERN_ALERT "goodbye,world
    ");
    }
    module_init(hello_init);
    module_exit(hello_exit);
    

      

    编写Makefile文件

    Makefile文件的编写如下,主要是KERNELDIR,为linux源码的位置

    ifeq ($(KERNELRELEASE),)
            KERNELDIR ?= /usr/src/linux-source-5.4.0
            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
    else
            obj-m := hello.o
    endif
    

      

    修改部分信息和执行

    当编译的内核为系统本身的内核,但是make以后生成的ko文件无法加载,即通过insmod xxx.ko无法加载,格式不对

    查看dmesg信息,参考解决:https://www.cnblogs.com/blfbuaa/p/6907027.html

    正常执行后再dmesg中会有相应的加载和卸载模块的message信息。卸载命令为rmmod xxx

    模块之间的依赖通信

    以下为add_sub.c

    #include<linux/kernel.h>
    #include<linux/module.h>
    #include"add_sub.h"
    long add_integer(long a,long b)
    {
            printk(KERN_ALERT "add init");
            return a+b;
    }
    long sub_integer(long a,long b)
    {
            printk(KERN_ALERT "sub init");
            return a-b;
    }
    EXPORT_SYMBOL(add_integer);
    EXPORT_SYMBOL(sub_integer);
    MODULE_LICENSE("Dual BSD/GPL");

    以下为add_sub.h

    #ifndef _ADD_SUB_H_
    #define _ADD_SUB_H_
    long add_integer(long a,long b);
    long sub_integer(long a,long b);
    #endif

    以下为Makefile,当执行完make后,则生成了符号表文件,其为Module.symvers,该文件可以用于其他文件的函数引用

    ifeq ($(KERNELRELEASE),)
            KERNELDIR ?= /usr/src/linux-source-5.4.0
            PWD := $(shell pwd)
            PRINT_INC =$(PWD)/../include
            EXTRA_CFLAGS += -I $(PRINT_INC)
    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
    else
            obj-m := add_sub.o
    endif

    以下为test.c

    #include<linux/kernel.h>
    #include<linux/module.h>
    #include"../add_sub.h"
    static long a = 1;
    static long b = 1;
    static int AddOrSub = 1;
    static int test_init(void)
    {
            long result = 0;
            printk(KERN_ALERT "test init
    ");
            if (1 == AddOrSub)
            {
                    result = add_integer(a,b);
            }
            else
            {
                    result = sub_integer(a,b);
            }
            //printk(KERN_ALERT, "the %s result is %ld", AddOrSub==1?"Add":"Sub",result);
            return 0;
    }
    static void test_exit(void)
    {
            printk(KERN_ALERT, "test_exit");
    }
    module_init(test_init);
    module_exit(test_exit);
    module_param(a,long,S_IRUGO);
    module_param(b,long,S_IRUGO);
    module_param(AddOrSub,int,S_IRUGO);
    MODULE_LICENSE("Dual BSD/GPL");
    

    以下为test.c的Makefile

    ifeq ($(KERNELRELEASE),)
            KERNELDIR ?= /usr/src/linux-source-5.4.0
            PWD := $(shell pwd)
    KBUILD_EXTRA_SYMBOLS=$(obj)/../print/Module.symvers
    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
    else
            obj-m := test.o
    endif

    编译完后,需要先挂载add_sub模块,然后再挂载test模块。

    未得到预期的效果,主要是在顺次加载后,并在加载过程添加a,b等参数,无法从dmesg中获得一个调用输出

    将模块编译到内核中

    如在drivers下建立add_sub_Kconfig文件夹,然后放入对应的源码文件,对应的Makefile和Kconfig文件。其中Kconfig文件用于make menuconfig的索引,其和上层的Kconfig关联

     Makefile文件内容如下:

    obj-$(CONFIG_ADD_SUB)+=add_sub.o
    obj-$(CONFIG_TEST)+=test.o
    

    Kconfig文件内容如下:

    #
    # add_sub configuration
    #
    
    menu "ADD_SUB"
            comment "ADD_SUB"
    config CONFIG_ADD_SUB
            tristate "ADD_SUB support"
            default y
    
    config CONFIG_TEST
            tristate "ADD_SUB test support"
            depends on CONFIG_ADD_SUB
            default y
    endmenu
    

    然后修改上层的Kconfig文件,添加如下内容:

    Source "drivers/add_sub_Kconfig/Kconfig"
    

    然后修改上层的Makefile文件,添加如下内容:

    obj-$(ADD_SUB)                  += add_sub_Kconfig/
    

    就可以在主目录下执行make menuconfig后,在驱动下找到对应的驱动和编译信息了

  • 相关阅读:
    明确方向,勇往直前
    每日一笔记之3:QTconnect()
    每日一笔记之2:QT之坐标系统:
    每日一笔记之1:静态成员函数
    QT对话框模式与非模式
    Objective-C-实例变量与属性的关系
    Objective-C编码规范
    CocoaPods的安装与使用
    design_model(18)observe
    design_model(17)state
  • 原文地址:https://www.cnblogs.com/bai2018/p/13799615.html
Copyright © 2020-2023  润新知