当前位置: 首页 > news >正文

3-Linux驱动开发-简单内核模块代码详解

单一模块hellomodule

代码结构:模块加载函数(必须) moudel_init模块卸载函数(必须) module_exit模块许可证声明(必须) MODULE_LICENSE模块参数模块导出符号模块的其他相关信息

hellomodule.c

//以下头文件都包含在以下目录
///home/kun/kernal_code/ebf_linux_kernel-ebf_4.19_star/include/linux
#include <linux/module.h>//包含内核模块信息声明的相关函数
#include <linux/init.h>//包含了 module_init() 和 module_exit() 函数的声明
#include <linux/kernel.h>//包含内核提供的各种函数,如 printkstatic int __init hello_init(void){printk(KERN_EMERG "[ KERN_EMERG ]  Hello  Module Init\n");printk( "[ default ]  Hello  Module Init\n");return 0;
}
/*
初始化函数 (hello_init)
static: C 语言关键字,表示此函数只在本文件内可见。
int: 它必须返回一个 int 值。0表示初始化成功。如果返回非 0 值,insmod 命令将会失败。
__init:宏,目的告诉编译器,这个函数(hello_init)只在初始化时使用一次。内核加载成功后,会把这个函数占用的内存释放。
printk:内核版的 printf。
KERN_EMERG:日志级别,紧急情况(Emergency),当日志级别非常高时,内核日志不仅会进入 dmesg,还会被推送到所有当前活动的终端(Tty)上。
printk 函数#define KERN_EMERG “<0>”通常是系统崩溃前的信息#define KERN_ALERT “<1>”需要立即处理的消息#define KERN_CRIT “<2>”严重情况#define KERN_ERR “<3>”错误情况#define KERN_WARNING “<4>”有问题的情况#define KERN_NOTICE “<5>”注意信息#define KERN_INFO “<6>”普通消息#define KERN_DEBUG “<7>”调试信息
*/static void __exit hello_exit(void)
{printk("[ default ]   Hello  Module Exit\n");
}
/*
退出函数 (hello_exit)
卸载 (rmmod) 时执行的函数。
__exit:宏。它告诉编译器,这个函数只在模块卸载时才需要。
*/module_init(hello_init);//宏,注册hello_init函数,告诉内核:当这个 .ko 文件被 insmod 加载时,请调用 hello_init 函数。
module_exit(hello_exit);//宏,注册hello_exit函数,告诉内核:当这个模块被 rmmod 卸载时,请调用 hello_exit 函数。MODULE_LICENSE("GPL2");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");
/*
模块元数据 (Module Metadata):描述信息,明模块的作者、功能和许可证
MODULE_LICENSE("GPL2"):模块的许可证,表示模块代码接受的软件许可协议,Linux 内核遵循 GPL V2 开源协议,内
核模块与 linux 内核保持一致即可。
MODULE_AUTHOR / MODULE_DESCRIPTION,描述作者和功能
MODULE_ALIAS("test_module"):别名允许您使用 modprobe(insmod 的智能版本)通过别名 test_module 来加载 hellomodule.ko。
*/

对应Makefile

KERNEL_DIR=/home/kun/kernal_code/ebf_linux_kernel-ebf_4.19_star/build_image/build
ARCH=arm
CROSS_COMPILE=arm-none-linux-gnueabihf-
export  ARCH  CROSS_COMPILE
#m 代表 Module(模块),请求编译一个内核模块
obj-m := hellomodule.o
#$(MAKE)等于 make 命令
#-C(Change Directory)切换目录,切换到KERNEL_DIR
#M= 代表Module(要编译的模块) $(CURDIR) 是一个内置变量,代表当前所在的目录/hellomodule
#modules,编译成的具体目标
all:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules.PHONE:clean copyclean:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean	copy:sudo  cp  *.ko  /home/embedfire/workdir

使用内核模块

#插入这个内核模块 insmod仅用于测试用
debian@lubancat:/mnt/host_projects$ sudo insmod hellomodule.ko
#插入成功的默认内容输出
Message from syslogd@lubancat at Nov 13 21:12:09 ...kernel:[  666.015524] [ KERN_EMERG ]  Hello  Module Init
#利用管道查看此内核module
debian@lubancat:/mnt/host_projects$ lsmod | grep hellomodule
hellomodule            16384  0
#删除这个内核模块
debian@lubancat:/mnt/host_projects$ sudo rmmod hellomodule.ko

系统自动加载模块

#复制 .ko 文件到官方目录
#挂载位置文件放入/lib/modules/$(uname -r)/
#$(...) (命令替换) uname -r 内核版本字符串
sudo cp hellomodule.ko /lib/modules/$(uname -r)/#注册更新模块数据库
sudo depmod -a #全局系统命令#添加到开机自启列表
sudo nano /etc/modules
#写入hellomodule#重启后查看
lsmod | grep hellomodule

内核模块传参与符号共享

函数说明

extern 
声明一个变量static int itype=0;
阻止任何C文件通过 C 语言的链接器直接看到或访问这个变量。module_param(name, type, permission)
加载时给模块传递数值,暴露接口给用户,加载时输入
permission规则一共四位开头0代表八进制。后面是三个组Owner,Group,Others权限数字r (Read - 读) = 4w (Write - 写) = 2x (Execute - 执行) = 1EXPORT_SYMBOL()
把函数或变量的内存地址,放入内核的全局符号表中,用于模块间通信,允许其他模块调用。

calculation.h

//目的就是告诉别处有定义,编译时候不要报错
#ifndef __CALCULATION_H__
#define __CALCULATION_H__
//这个变量在别处定义
extern int itype;
//声明函数原型
int my_add(int a, int b);
int my_sub(int a, int b);
#endif

calculation.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>#include "calculation.h"static int __init calculation_init(void){printk(KERN_ALERT "calculation  init!\n");printk(KERN_ALERT "itype+1 = %d, itype-1 = %d\n", my_add(itype,1), my_sub(itype,1));    return 0;}static void __exit calculation_exit(void)
{printk(KERN_ALERT "calculation  exit!\n");
}module_init(calculation_init);
module_exit(calculation_exit);MODULE_LICENSE("GPL2");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("calculation module");
MODULE_ALIAS("calculation_module");

parametermodule.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>static int itype=0;
module_param(itype,int,0);static bool btype=0;
module_param(btype,bool,0700);static char ctype=0;
module_param(ctype,byte,0);static char  *stype=0;
module_param(stype,charp,0644);static int __init param_init(void){printk(KERN_ALERT "param init!\n");printk(KERN_ALERT "itype=%d\n",itype);printk(KERN_ALERT "btype=%d\n",btype);printk(KERN_ALERT "ctype=%d\n",ctype);printk(KERN_ALERT "stype=%s\n",stype);return 0;
}static void __exit param_exit(void)
{printk(KERN_ALERT "module exit!\n");
}EXPORT_SYMBOL(itype);int my_add(int a, int b){return a+b;}EXPORT_SYMBOL(my_add);int my_sub(int a, int b){return a-b;}EXPORT_SYMBOL(my_sub);module_init(param_init);
module_exit(param_exit);MODULE_LICENSE("GPL2");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("module_param");
MODULE_ALIAS("module_param");

make后生成了相关文件
在这里插入图片描述
calculation.ko依赖parametermodule.ko中的参数itype和定义的函数(EXPORT_SYMBOL暴露的)
板子上使用时:

#要先加载parametermodule.ko再加载calculation.ko, 卸载类似出栈,module_param的传参
sudo insmod parametermodule.ko itype=123 btype=1 ctype=200 stype=abc
sudo insmod calculation.ko
http://www.dtcms.com/a/614363.html

相关文章:

  • 北京住房城乡建设部网站云南技术网站建设销售
  • Unity游戏开发客户端面试题分享
  • Hugging Face Transformers:AI模型的“瑞士军刀“
  • 中国纪检监察报网站wordpress古腾堡汉化
  • L2 MAC层核心机制介绍
  • 互动即价值?社交型数字资产深度融合社交行为与价值创造:
  • c#.net List对象和字典对象Dictionary,HashSet对比
  • 自己做免费网站的视频做跨境电商要什么费用
  • 唯品会 item_get 接口对接全攻略:从入门到精通
  • 互联网站账户e服务平台怎么建立一个网站好
  • 网站标题如何修改江苏高端品牌网站建设
  • 软考程序员2021年C语言链表案例题解答
  • nfs练习作业
  • 红黑树分析 1
  • Linux:监控命令
  • 官方网站开发用什么语言厦门建网站的公司
  • 做网站设计需要哪些软件兖州做网站
  • 马来西亚医疗旅游理事会举办“2025马来西亚深圳医疗旅游周“发力中国医疗旅游市场
  • wordpress 微信授权做网站建设优化的公司排名
  • 网站制作招聘音乐网站可做哪些内容
  • 一块中国好屏,和智能终端共舞
  • 240. Java 集合 - 使用集合工厂方法创建和处理数据
  • 南京app定制台州商品关键词优化
  • 代码生成工具Amazon CodeWhisperer介绍
  • 做视频网站的流程注册公司流程需要多久
  • 域名与空间购买后怎么做网站一般网站海报做一张多久
  • 网站建设合同规定橘子建站是什么
  • LangChain框架入门:全方位解析记忆组件
  • Python如何写一个可迭代对象
  • 命名规范snake_case