• 一个Kbuild工程生成多个ko文件及其在驱动单元测试上的应用


    背景

    Linux驱动是基于Kbuild框架开发的,一般情况下只会生成一个ko文件,如果想添加单元测试(Unit Test即UT),用户要么在模块入口函数的末尾添加UT代码,要么额外创建一个单独的UT工程,前者把测试代码跟驱动代码放置于同一个文件比较混乱,后者创建额外的工程维护比较麻烦。

    能否既避免混乱,又避免麻烦呢?可以的。

    思路

    Kbuild支持生成多个ko,只需要给Makefile变量obj-m追加一个模块名即可。

    MODULE_NAME := your_drv
    MODULE_UT_NAME := your_drv_ut
    
    SRCS := your_drv_part1.c your_drv_part2.c
    SRCS_UT := your_drv_ut_suite1.c
    
    $(MODULE_NAME)-objs := $(SRCS:%.c=%.o)
    $(MODULE_UT_NAME)-objs := $(SRCS_UT:%.c=%.o)
    
    obj-m := $(MODULE_NAME).o
    obj-m += $(MODULE_UT_NAME).o
    
    clean-objs := $(SRCS:%.c=%.o)
    clean-objs += $(join $(dir $(SRCS)), $(patsubst %.c, .%.o.cmd, $(notdir $(SRCS))))
    clean-objs += $(SRCS_UT:%.c=%.o)
    clean-objs += $(join $(dir $(SRCS_UT)), $(patsubst %.c, .%.o.cmd, $(notdir $(SRCS_UT))))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注意:

    1. 模块追加是通过+=操作符实现的
    2. 模块的.c源文件不要跟模块名重复,否则链接程序ld会报no input files,原因是同名导致的循环依赖被make程序检测到,从而丢弃该源文件。

    UT实践

    UT框架选择

    如果你是5.5以上版本的内核,则建议使用内核自带的kunit框架,不用引入额外依赖,功能也基本够用。

    kunit用法示例

    #include 
    
    void your_drv_test_basic(struct kunit *test)
    {
    	int reg_value = 0;
    	
    	// ...
    	KUNIT_EXPECT_EQ(test, reg_value, 42);
    }
    
    AX_S32 your_drv_test_init(struct kunit *test)
    {
    	// 一些资源分配
    }
    
    AX_S32 your_drv_test_exit(struct kunit *test)
    {
    	// 一些资源回收
    }
    
    static struct kunit_case your_drv_test_cases[] = {
    				KUNIT_CASE(your_drv_test_basic),
                    {}
    };
    
    struct kunit_suite your_drv_test_suite1 = {
        .name = "your_drv kunit",
        .init = your_drv_test_init,
        .exit = your_drv_test_exit,
        .test_cases = your_drv_test_cases,
    };
    kunit_test_suites(&your_drv_test_suite1);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("your name");
    MODULE_DESCRIPTION("your_drv unit test");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    kunit运行示例

    # 先加载kunit和你的驱动ko
    insmod kunit.ko
    insmod you_drv.ko
    # 再加载ut的ko,ut代码会在模块加载时执行
    insmod you_drv_ut.ko
    
    • 1
    • 2
    • 3
    • 4
    • 5

    一些补充

    1. Kbuild是基于Makefile的,所以掌握Makefile的语法对定制Kbuild工程至关重要。
    2. 如果要添加多个test suite,则需要定义多个kunit_suite结构体(必要的话将每个suite拆分到单独的.c文件,这样的话记得给UT模块添加多个.c文件),并将其一并传递给kunit_test_suites函数(该函数支持可变数目的参数)
  • 相关阅读:
    /dev/kmem & /proc/kallsyms
    【统计学习方法】P2 监督学习
    Qt5开发从入门到精通——第一篇(概述——(信号和槽机制)、(原对象系统)、(布局管理器))
    为什么说Python 是胶水语言?
    单例模式定义及其基础示例
    window10彻底关闭系统管理员控制(所有软件以管理员身份运行)
    Centos7修改主机名hostname
    ZYNQ实验--裸机程序固化
    基于京东micro-app微前端框架的项目实践
    移动硬盘显示要格式化怎么办?
  • 原文地址:https://blog.csdn.net/happen23/article/details/126654733