首页 > 其他分享 >构造和运行模块

构造和运行模块

时间:2024-05-10 14:55:22浏览次数:24  
标签:使用 module 装载 MODULE 模块 构造 运行 内核

构造和运行模块

在尝试运行模块之前,需要使用合适的系统(通常是封闭的)实现内核原代码的相应实验

Hello world模块

  • 模块构造/析构: 使用module_init/module_exit宏装饰相应函数,实现内核模块的装载/移除
  • 许可证: 使用MODULE_LICENSE(" ")实现对许可证的装载;
  • 模块的装载与移除: 装载insmod;移除rmmod

核心模块与应用程序的对比

  • 应用程序: 执行单个任务;可以将资源释放扔给系统;可以使用广泛的库函数;可以使用调试器处理段错误。
  • 模块: 注册以便服务请求-事件驱动;退出时需要撤销初始化函数所实现的一切;只能使用内核所实现的函数;内核错误会影响整个系统。
  • 链接模块到内核过程(insmod): 其本质是一个modutiles模块应用程序,执行init_module函数
    • 计算模块代码、模块名、module对象的内存大小
    • 用户空间分配内存区,拷贝相应代码;init域指向入口函数分配地址;exit域指向出口函数分配地址;
    • 调用init_module(linux/kernel/module.c的SYSCALL_DEFINE3),传递用户区内存区地址;
    • 声明内核应用模块,并呼叫初始化函数
    • 释放用户态内存

用户空间和内空间

  • 操作系统的核心作用: 提供对计算机硬件的一致视图;并保证程序的独立操作和阻止资源的非法访问
  • 模块化代码在内核空间运行,其作为系统调用的一部分

内核中的并发

  • 核心思想: 在同一时刻,会有许多事情正在发生;
  • 并发问题的来源: Linux系统的进程并发性;中断程序的异步性;软件抽象的异步性;SMP系统;可抢占的进程调度策略;
  • 并发问题带来的要求: Linux内核代码的可重入性(处理并发问题并避免竞态);
  • 并发问题的注意事项: 不能假定在给定代码段中对处理器的独占性。

当前进程

  • 当前进程可以使用current获得:<asm.current.h>和<linux/sched.h> 或<linux/sched.h>
  • 打印当前进程信息: printk(KERN_INFO "The process is \" &s\" (pid &i)\n" current->comm, current->pid);

其他细节

  • 栈的分配: 内核栈较小,因此如果需要大结构,应该动态分配;
  • 内核API命名: __开头函数为内核底层组件,谨慎使用;
  • 浮点运算: 内核代码通常不支持浮点运算;其是使用软浮点实现的(通过编译器)或在在编译时候打开浮点运算单元的支持,并在Makefile添加相应编译浮点指令;

编译和装载

编译模块

  • 参考文件 Documentation/kbuild, 工具版本:Documentation/Changes

  • 添加makefile: obj - m := module.o 与 module-objs := file1.o file2.o

  • 对文件的编译依赖于内核的makefile:

    参考代码:
    ifeq ($(DEBUG),y)
      DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
    else
      DEBFLAGS = -O2
    endif
    
    EXTRA_CFLAGS += $(DEBFLAGS)
    EXTRA_CFLAGS += -I$(LDDINC)
    
    ifneq ($(KERNELRELEASE),)
    # call from kernel build system
    
    scull-objs := main.o pipe.o access.o
    
    obj-m	:= scull.o
    
    else
    
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    PWD       := $(shell pwd)
    
    modules:
    	$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
    
    endif
    

装载和卸载模块

  • insmod工具: 参照上文的链接模块到内核过程(insmod)
  • modprobe工具: 相较于insmod,其会检查所装载模块的依赖性,并在当前路径搜索并一并加载
  • rmmod注意事项: 使用状态/配置为禁止移除模块无法移除
  • 模块调试:读取/proc/modules获得模块信息,读取/sys/module获得当前已装载模块信息;

版本依赖

  • 内核兼容性检查: 通过链接ermagic.o,实现在装载时内核模块版本匹配的检查,并查看/ver/log中相应的log文件查看失败原因。
  • 模块兼容性: 使用 #ifdef 对代码进行构造/编译,可以使用linux/version.h的定义,其被linux/module.h自动包含
    • 常用宏:UTS_RELEASE(内核版本字符串)、LINUX_VERSION_CODE(内核版本二进制表示)、KERNEL_VERSUON(major, minor, release)(将已知版本字符串转化为二进制表示)
    • 封装:将特定版本的底层实现隐藏封装在特定头文件中,并通过低层宏/函数实现

平台依赖

  • 内核开发对平台的依赖: 内核可根据不同需求指定寄存器
  • 平台依赖的检查: 链接ermagic.o,可以实现对处理器相关部分配置的选项检查
  • 一般性的发布: 考虑到不同平台的兼容性(GPL)

内核符号表

  • 内核符号表作用: insmod使用内核符号表对模块进行解析,通常来说,模块的符号是不用导出的,但是如果与其他模块存在依赖关系时,其符号需要导出(模块层叠技术)。
  • 模块层叠技术的应用: fat-> msdos、usbcore + input -> USB、并口子系统(Ip、parport、parport_pc、内核API);其实就是设计模式中的装饰与组合
  • 处理层叠模块: modprobe可以从标准的已安装模块目录实现装入模块;
  • 全局宏导出符号: EXPORT_SYMBOL(name)或EXPORT_SYMBOL_GPL(name),其将全局变量保存在ELF段。其原理为于<linux/module.h>中

预备知识

  • 代码要求:
    • 模块头文件:
    #include<linux/module.h>
    #include<linux/init.h>
    #include<linux/moduleparam.h>
    
    • 许可证等MODULE:
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR();
    MODULE_DESCPTION();
    MODULE_VERSION();
    MODULE_ALIAS();
    MODULE_DEVICE_TABLE();
    

初始化和关闭:

  • 初始化:
    static int __init initialisztion_fun(void)
    {
    
    }
    module_init(initialisztion_fun);
    
  • 模块的注册:使用相应的内核函数实现注册-软件抽象;层叠功能:EXPORT—_SYMBOL或者register;
  • 清除:
    static void __exit cleanup_fun(void)
    {
    
    }
    module_exit(cleanup_fun);
    
  • 初始化错误处理: 检查返回值,确保操作成功;初始化错误处理应该继续向前并尽可能提供功能;如无法装载模块,应撤销之前工作;
    • 常用语句: 使用goto语句处理错误,一旦出错,调用goto + 清除函数(检查状态);
    • 错误代码: 尽量使用<linux/errno.h>中的符号值,使其存在意义;
  • 竞态: 在支持某个设备的内部初始化完成之前,不要注册任何设施;初始化失败,但是内核已经使用注册设备,需等待操作完成;

模块参数:

  • 模块参数赋值: 装载模块(insmode/modprobe),配置文件(modprobe)(etc/modprobe.conf)
  • 模块参数加载 module_param(name, type[,num], perm) []中的为数组可选;注意参数一定为static并给定默认值
    • type类型:bool、invbool、charp、int、long、short、uint、ulong、ushort
    • 可使用hook定义其他类型,见moduleparam.h
    • parm为访问许可值,其定义位于<linux/stat.h>, 如果其为0,则没有其对应的sysfs项目,对于该参数,其尽量设置为只读(S_IRUGO)因为内核不会通知模块

用户空间编写驱动程序

  • 其表现为一个服务器进程,其多用于新的,不常见硬件的编程开发
  • 注意: 无法使用中断/只能用mmap映射访问内存/只能用ioperm或iopl访问端口/响应时间慢/使用mlock防止换出/不能处理重要设备

快速参考(P44-P45)

参考文献

Insmod模块加载过程分析 https://www.cnblogs.com/edver/p/8419897.html
The Linux Kernel https://linux-kernel-labs.github.io/refs/heads/master/labs/kernel_modules.html#objdump

标签:使用,module,装载,MODULE,模块,构造,运行,内核
From: https://www.cnblogs.com/David-Dong/p/18180863

相关文章

  • dokcer-compose.yml 方式运行 mysql 8.0
    先不映射指定配置目录,./conf/mysql,docker容器开起来后,复制容器内/etc/mysql到宿主机,然后添加目录映射:-"./conf/mysql:/etc/mysql",这样就可以将配置里保存在宿主机了。version:'3.0'networks:mysql_network:name:mysql_networkexternal:trueservices:......
  • Linux nginx 玩转日志模块
    log_formatmain'$remote_addr-$remote_user[$time_local]"$request"''$status$body_bytes_sent"$http_referer"''"$http_user_agent""$http_x_forwarded_fo......
  • Unity Editor下运行DoTween动画
    DOTweenEditorPreview.PrepareTweenForPreview(tar.GetTween());DOTweenEditorPreview.Start();以Test脚本为例:publicclassUTest:MonoBehaviour{publicTweenGetTween(){vartw=transform.DOMove(Vector3.left,2);tw.onUpdate=()=>......
  • k8s中如何控制pod运行的节点
    在Kubernetes(K8s)中,可以通过几种方式来控制Pod运行的节点。以下是一些常用的方法:使用nodeName:在Pod的YAML定义中,你可以使用nodeName字段来指定Pod应该运行在哪个节点上。nodeName字段的值应该是目标节点的名称。如果节点不存在或者不可调度,Pod将不会被创建。使用nodeSele......
  • python教程9-第三方模块安装
    https://pypi.python.org/pypi是python的开源模块库。收录了⾃全世界python开发者贡献的模块,⼏乎涵盖了你想⽤python做的任何事情。事实上每个python开发者,只要注册⼀个账号就可以往这个平台上传你⾃⼰的模块,这样全世界的开发者都可以容易的下载并使⽤你的模块。下载和安装:......
  • PHP代码运行时两个foreach迭代变量一样导致错误
    请看如下代码:$list=[1,2,4,5];$list2=[5,6,7,9];foreach($listas$key=>&$value){$value=strval($value);}foreach($list2as$key=>$value){$value=11;}pre($list);......
  • FMC160-两路14位400Msps AD,两路16位400Msps DA FMC子卡模块
    FMC160-两路14位400MspsAD,两路16位400MspsDAFMC子卡模块一、概述 该板卡可实现2路14bit400MspsAD和2路16bit400MspsDA功能,遵循VITA57标准,北京太速科技板卡可以直接与VME/VXS/AMC/VPX/PCI-EFPGA载板连接使用,用于模拟信号、中频信号采集,信号发出等......
  • GPS标准时钟系统(考场子母钟系统)设计构造原理特点
    GPS标准时钟系统(考场子母钟系统)设计构造原理特点GPS标准时钟系统(考场子母钟系统)设计构造原理特点京准电子科技官微——ahjzsz【摘要】时钟系统是校园网络中一个重要的精准计时系统,随着网络的普及,许多校园都建了自己的校园专网,使用的网络设备和服务器也日益增多,这些设备都有自己......
  • ansible03-ansible模块
    所有模块一览https://blog.csdn.net/sj349781478/article/details/106898574?utm_source=app&app_version=4.13.0command模块默认模块可以不写ansible  host  -a  'chdir=/datals'ansible  host  -a  'creates=/root/testls'ansible  host  -a  'remo......
  • WPF 引用类库中的图片在设计器的时候显示,运行起来不显示
    我这边是建立了一个类库,然后把所有静态资源放在该类库中,然后主项目添加该项目引用,然后图片死活不显示  1.图片属性设置为资源2.主项目添加该项目引用操作都试过了,就是死活不显示,然后问了别人,让我删除类库重新建一个试试,然后试了下,诶,好像确实可以了,突然想起一个小细节,我......