首页 > 其他分享 >内核模块高级-多文件编译、加载、参数传递、模块依赖

内核模块高级-多文件编译、加载、参数传递、模块依赖

时间:2024-07-21 21:55:33浏览次数:21  
标签:int void ext module 参数传递 init 模块 内核模块 加载

多文件编译

        对于比较复杂的驱动程序,常常会把它的功能进行拆分,由不同的文件实现,这样也能进行并行开发,缩短开发周期。多文件编译的简单例子如下:

mod.c:

//mod.c

#include <linux/init.h>
#include <linux/module.h>
#include "ext.h"//其他文件的头文件ext.h

static int hello_init(void)
{
    printk("Hello World.\n");
    xxx_init();//调用其他文件的函数,实现在ext.c
    return 0;
}
​
static void hello_exit(void)
{
     printk("Goodbye World.\n");
     xxx_exit();//调用其他文件的函数,实现在ext.c
}
​
module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Ono Zhang");
MODULE_DESCRIPTION("A simple Hello World Module");

ext.h:

//ext.h
#ifndef __EXT_H__
#define __EXT_H__

void xxx_init(void);
void xxx_exit(void);

#endif

ext.c

//ext.c
#include <linux/kernel.h>

void xxx_init(void)
{
    printk("Init extern.\n");
}

void xxx_exit(void)
{
    printk("Exit extern.\n");
}

Makefile

obj-m = mymod.o 
mymod-objs = mod.o ext.o

KDIR = /home/linux-kernel
PWD =$(shell pwd)

modules:
    $(MAKE) -C $(KDIR) M=$(PWD) modules

其中KERNELDIR是内核源码目录所在的路径。

新增了ext.c及ext.h,在里面定义了xxx_init机xxx_exit函数。在Makefile里面的第2行“mymod-objs=mod.o ext.o”表示mymod模块是由mod.o和ext.o两个目标文件共同生成的,最后生成的文件为mymod.ko。

加载

1、若编辑进内核,见《内核模块编写及编译》的编译章节,则linux启动时,会自动加载模块,调用的函数栈如下:

init/main.c
start_kernel -> reset_init -> kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
                                   |
                                   |->static int __ref kernel_init(void *unused)
                                            |
                                            |-> kernel_init_freeable( )
                                                   |
                                                   |-> do_basic_setup();
                                                        |
                                                        |——> do_initcalls();
                                                                |
                                                                |->do_initcall_level()

2、若单独编译 *.ko,见《内核模块编写及编译》的编译章节,需要使用命令进行加载,加载命令如下:

insmod mymod.ko //mymod.ko为上节编译出的ko文件

也可以使用:

modprobe mymod //mymod为上节编译出的模块名

modprobe和insmod的区别,我们在模块依赖章节介绍。

其调用栈为:

kernel/module.c
finit_module-->static int load_module(struct load_info *info, const char __user *uargs,int flags)
		                     |
		                     |->static int do_init_module(struct module *mod)

参数传递

       在应用开发中,可以给main()函数传递参数,这样应用程序就能知道最初的控制参数是什么,当然也可以选择不向应用程序传递参数。在驱动开发中,也可以向内核模块传递参数,需要使用宏module_param或者module_param_array。

module_param(参数名,参数类型,参数权限)
module_param_array (参数名, 参数类型, 数组元素个数指针, 参数权限); 

       另外使用MODULE_PARM_DESC来描述参数作用。

MODULE_PARM_DESC(参数名,参数描述)

        内核支持参数类型有bool、invbool、charp(字符串指针)、short、int、long、ushort、uint、ulong。这些类型又可以复合成对应的数组类型。

        参考例子如下:

#include <linux/init.h>
#include <linux/module.h>

int a = 0;
int b[10] = {1, 2, 3};
int c = 0;
char *d = "456ab";

module_param(a, int, 0664);
module_param_array(b, int, &c, 0664);
module_param(d, charp, 0664);

static int hello_init(void)
{
    int i = 0;
    printk("Hello World.\n");
    printk("a = %d\n", a);
    for (i = 0; i < 10; i++)
    {
        printk("b[%d] = %d\n", i, b[i]);
    }

    printk("c = %d\n", c);

    printk("d is %s\n", d);
    return 0;
}

static void hello_exit(void)
{
    printk("Goodbye World.\n");
    return;
}
module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Ono Zhang");
MODULE_DESCRIPTION("A simple Hello World Module");

         加载:

    1、若编译进内核,在bootloader中可向内置的模块传递参数,例如可以在bootargs中设置模块名.参数名=值的形式给该内置的模块传递参数。

    2、若单独编译 *.ko,使用insmod xxx.ko 参数名=值,如上例子为:

sudo insmod mod.ko a=10 b=12,3,5 d=ws

         打印回显为:

[ 4729.691707] a = 10
[ 4729.691708] b[0] = 12
[ 4729.691709] b[1] = 3
[ 4729.691710] b[2] = 5
[ 4729.691710] b[3] = 0
[ 4729.691711] b[4] = 0
[ 4729.691712] b[5] = 0
[ 4729.691712] b[6] = 0
[ 4729.691713] b[7] = 0
[ 4729.691713] b[8] = 0
[ 4729.691714] b[9] = 0
[ 4729.691714] c = 3
[ 4729.691715] d is ws

加载完成后,希望修改它的值,需要在sys文件系统中找到对应的文件节点/sys/module/模块名/parameters/参数名,可以使用echo和cat来修改及查询参数的值。

如:

cat /sys/module/mod/parameters/a
10
echo 20 > /sys/module/mod/parameters/a
cat /sys/module/mod/parameters/a
20

    

模块依赖

       模块依赖是指A模块引用了B模块的函数或者全局变量,A模块就依赖于B模块,B模块就是被依赖的模块,加载模块时,需要先加载B模块,再加载A模块。另外A模块使用B模块的函数或者全局变量,需要在B模块中导出,否则A模块会编译出错,导出使用宏EXPORT_SYMBOL。

EXPORT_SYMBOL(函数名或者变量名)

标签:int,void,ext,module,参数传递,init,模块,内核模块,加载
From: https://blog.csdn.net/qq_40896451/article/details/140592655

相关文章

  • 解决Element UI 表格组件懒加载数据刷新问题
    一、问题描述elementui的table组件设置成懒加载时,遇到数据表格需要更新、删除等操作,子节点不会自动更新。二、解决思路刷新数据,就是重新调用load(),通过map记录已展开的节点,需要刷新数据时,取出对应treeNode,调用load()进行数据刷新。三、代码实现(VUE)exportdefault{data(......
  • pytorch学习(八)Dataset加载分类数据集
    我们之前用torchvision加载了pytorch的网络数据集,现在我们用Dataset加载自己的数据集,并且使用DataLoader做成训练数据集。图像是从网上下载的,网址是点这里,标签是图像文件夹名字。下载完成后作为自己的数据集。1.加载自己的数据集的思路  1)要完成继承自Dataset的类的构......
  • android audio 相机按键音加载与修改
    相机按键音资源,加载文件路径:frameworks/av/services/camera/libcameraservice/CameraService.cpp按键音,加载函数: voidCameraService::loadSoundLocked(sound_kindkind){   ATRACE_CALL();     LOG1("CameraService::loadSoundLockedref=%d",mSoundRe......
  • bug处理--antdesign中umi升级后无法加载子页面
    bug处理--antdesign中umi升级后无法加载子页面historyconstAdmin:React.FC=(props)=>{ const{children}=props; return( <PageHeaderWrapper> {children} </PageHeaderWrapper> );};now升级到Umi4后,之前的一些组件不能用了,获取不到props,props......
  • 如何在 kivy 中的应用程序文件中保存和加载设置?
    我一直在使用配置对象来存储和检索kivy中应用程序的设置。问题是配置对象是全局的,并且是为系统中的所有kivy应用程序设置的。我当前使用的内容:fromkivy.configimportconfig...AppcodeclassUserAPP(App);defbuild(self)defbuild_config(self,con......
  • 在 PowerShell 中,可以编写脚本来检测本地加载和远程加载的情况。这通常涉及到检查计算
    在PowerShell中,可以编写脚本来检测本地加载和远程加载的情况。这通常涉及到检查计算机上的特定服务或应用程序的状态或配置。以下是一些示例脚本和方法,可以用来实现这些检测:检测本地加载示例:检查本地服务的运行状态powershellCopyCode#检查本地服务状态$serviceName="M......
  • 在 PowerShell 中,"本地加载"和"远程加载"通常指的是运行脚本或命令的位置或方式。以下
    在PowerShell中,"本地加载"和"远程加载"通常指的是运行脚本或命令的位置或方式。以下是关于本地加载和远程加载的一些基本概念和示例:本地加载本地加载指的是在当前计算机上执行PowerShell脚本或命令。这些脚本和命令直接在本地计算机上运行,无需通过网络连接到其他计算机或服......
  • 同时加载 2 个 Tkinter 窗口。一个有动画的
    以下脚本独立运行以运行场景:首先打印结果,然后以动画结束绘图。importnumpyasnpimportmatplotlib.pyplotaspltimporttkinterastkfromtkinterimportttkfrommatplotlib.animationimportFuncAnimationdefrun_model():#Inputparameters(examplev......
  • 易优CMS模板标签load文件加载导入外部的css样式文件
    【基础用法】标签:load描述:资源文件加载,比如:css/js用法:{eyou:loadhref='/static/js/common.js'ver='on'/}属性:file=''资源文件路径href=''远程资源文件URLver=''开启版本号自动刷新浏览器缓存涉及表字段:无【更多示例】-------------------------------示例1------......
  • 加载 iptables 相关模块
    在现代Linux系统中,连接跟踪(ConnectionTracking)功能已经集成到nf_conntrack模块中,不再需要单独加载ip_conntrack模块。相应的nf_conntrack模块负责处理IPv4的连接跟踪功能,而IPv6的连接跟踪功能由nf_conntrack_ipv6模块处理。如果你需要加载与连接跟踪相关的模块,可以使用......