• 驱动开发1 概念、内核模块编程、内核消息打印函数printk函数的使用、内核模块传参、内核导出符号


    1 驱动相关概念

    2 内核模块编程

    内核模块编写实例代码+注释

    1. #include
    2. #include
    3. //入口函数,安装内核模块时执行
    4. static int __init mycdev_init(void)
    5. {
    6. //static 修饰当前函数只能在本文件使用
    7. //int 函数的返回值类型,如果函数规定返回值但是没有加返回值,编译会报错
    8. //mycdev_init函数名,可以自己起名字
    9. //void表示函数无参数,当没有参数时void一定要加,不然报错
    10. //__init的作用是用来告诉编译器当前代码保存在.init.text段中
    11. //#define __init __section(".init.text")
    12. //linux内核也会有自己的链接脚本 vmlinux.lds,这个链接脚本里规定了不同的内容在
    13. //内存中的什么位置
    14. return 0;
    15. }
    16. //出口函数,卸载内核模块时执行
    17. static void __exit mycdev_exit(void)
    18. {
    19. //#define __exit __section(".exit.text")
    20. //__exit指定出口函数保存在.exit.text段中
    21. }
    22. //用于声明入口函数
    23. module_init(mycdev_init);
    24. //用于声明出口函数
    25. module_exit(mycdev_exit);
    26. //声明当前内核模块遵循GPL协议
    27. MODULE_LICENSE("GPL");

    内核模块编译(外部编译Makefile)

    1. #保存UBUNTU内核源码路径
    2. KERNELDIR := /lib/modules/$(shell uname -r)/build
    3. #KERBELDIR保存开发板内核源码路径
    4. #KERNELDIR := /home/ubuntu/linux-5.10.61/
    5. #PWD保存当前内核模块的路径
    6. PWD := $(shell pwd)
    7. all:
    8. #make modules是模块化编译命令
    9. #make -C $(KERNLEDIR) 执行make之前先切换到KERNELDIR对应的路径
    10. #M=$(PWD)表示进行模块化编译的路径是PWD保存的路径
    11. make -C $(KERNELDIR) M=$(PWD) modules
    12. clean:
    13. #编译清除
    14. make -C $(KERNELDIR) M=$(PWD) clean
    15. #将obj-m保存的文件单独链接为内核模块
    16. obj-m := demo.o

    通用版本的Makefile

    1. modname ?= demo
    2. arch ?= arm
    3. ifeq ($(arch),arm) #通过命令行传过来的架构决定怎么编译
    4. #KERBELDIR保存开发板内核源码路径
    5. KERNELDIR := /home/ubuntu/linux-5.10.61/
    6. else
    7. #保存UBUNTU内核源码路径
    8. KERNELDIR := /lib/modules/$(shell uname -r)/build
    9. endif
    10. #PWD保存当前内核模块的路径
    11. PWD := $(shell pwd)
    12. all:
    13. #make modules是模块化编译命令
    14. #make -C $(KERNLEDIR) 执行make之前先切换到KERNELDIR对应的路径
    15. #M=$(PWD)表示进行模块化编译的路径是PWD保存的路径
    16. make -C $(KERNELDIR) M=$(PWD) modules
    17. clean:
    18. #编译清除
    19. make -C $(KERNELDIR) M=$(PWD) clean
    20. #将obj-m保存的文件单独链接为内核模块
    21. obj-m := $(modname).o

    3 内核消息打印函数printk函数的使用

    代码示例

    1. #include
    2. #include
    3. // 入口函数,安装内核模块时执行
    4. static int __init mycdev_init(void)
    5. {
    6. // static 修饰当前函数只能在本文件使用
    7. // int 函数的返回值类型,如果函数规定返回值但是没有加返回值,编译会报错
    8. // mycdev_init函数名,可以自己起名字
    9. // void表示函数无参数,当没有参数时void一定要加,不然报错
    10. //__init的作用是用来告诉编译器当前代码保存在.init.text段中
    11. // #define __init __section(".init.text")
    12. // linux内核也会有自己的链接脚本 vmlinux.lds,这个链接脚本里规定了不同的内容在
    13. // 内存中的什么位置
    14. printk(KERN_ERR "hello world\n");
    15. int a=10;
    16. printk(KERN_ERR "%d\n",a);
    17. return 0;
    18. }
    19. // 出口函数,卸载内核模块时执行
    20. static void __exit mycdev_exit(void)
    21. {
    22. // #define __exit __section(".exit.text")
    23. //__exit指定出口函数保存在.exit.text段中
    24. }
    25. // 用于声明入口函数
    26. module_init(mycdev_init);
    27. // 用于声明出口函数
    28. module_exit(mycdev_exit);
    29. // 声明当前内核模块遵循GPL协议
    30. MODULE_LICENSE("GPL");

    4 内核模块传参

    1. #include
    2. #include
    3. int a=10;
    4. module_param(a,int,0664);//声明变量a可以进行命令行传参
    5. MODULE_PARM_DESC(a,"this is a int value");//添加要传参的变量描述
    6. static int __init mycdev_init(void)
    7. {
    8. printk("a=%d\n",a);
    9. return 0;
    10. }
    11. static void __exit mycdev_exit(void)
    12. {
    13. }
    14. module_init(mycdev_init);
    15. module_exit(mycdev_exit);
    16. MODULE_LICENSE("GPL");

    5 内核导出符号

    1 定义demo1.c,demo1.c中完成函数的定义

    1. #include
    2. #include
    3. int add(int i,int j)
    4. {
    5. return i+j;
    6. }
    7. //生成add的符号表文件
    8. EXPORT_SYMBOL(add);
    9. static int __init mycdev_init(void)
    10. {
    11. return 0;
    12. }
    13. static void __exit mycdev_exit(void)
    14. {
    15. }
    16. module_init(mycdev_init);
    17. module_exit(mycdev_exit);
    18. MODULE_LICENSE("GPL");

    2 创建demo2.c,里面完成demo1.c里面函数的调用

    1. #include
    2. #include
    3. extern int add(int i,int j);
    4. static int __init mycdev_init(void)
    5. {
    6. printk("调用模块1函数执行结果为:%d",add(3,5));
    7. return 0;
    8. }
    9. static void __exit mycdev_exit(void)
    10. {
    11. }
    12. module_init(mycdev_init);
    13. module_exit(mycdev_exit);
    14. MODULE_LICENSE("GPL");

  • 相关阅读:
    Hi3516DV500 SVP_NNN添加opencv库记录
    [附源码]Python计算机毕业设计宠物销售管理系统
    WebGPU 入门:绘制一个三角形
    泛微全新低代码平台e-builder在沪发布,超千名与会者共商数字化转型
    [附源码]计算机毕业设计springboot天狗电子商城系统
    数据结构题型14-二叉树的遍历
    c++并发线程之创建线程、 join、detach、joinable、线程临时变量问题、ref使用
    前端面试题目小结 之一(精选10题)
    秒验丨Android端SDK API使用说明
    图形学-几何
  • 原文地址:https://blog.csdn.net/Smallxu_/article/details/133930433