解密module_init

Linux C++: error: redefinition of ‘class xxx’ 的解决方法 阅读详情

在Linux底下写过driver模块的对这个宏一定不会陌生。module_init宏在MODULE宏有没有定义的情况下展开的内容是不同的,如果这个宏没有定义,基本上表明阁下的模块是要编译进内核的(obj-y)。
1.在MODULE没有定义这种情况下,module_init定义如下:
#define module_init(x) __initcall(x);
因为
#define __initcall(fn)                            device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
所以,module_init(x)最终展开为:
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
更直白点,假设阁下driver所对应的模块的初始化函数为int gpio_init(void),那么module_init(gpio_init)实际上等于:
static initcall_t  __initcall_gpio_init_6 __used __attribute__((__section__(".initcall6.init"))) = gpio_init;
就是声明一类型为initcall_t(typedef int (*initcall_t)(void))函数指针类型的变量__initcall_gpio_init_6并将gpio_init赋值与它。
这里的函数指针变量声明比较特殊的地方在于,将这个变量放在了一名为".initcall6.init"节中。接下来结合vmlinux.lds中的
.initcall.init : AT(ADDR(.initcall.init) - (0xc0000000 -0x00000000)) {
   __initcall_start = .;
   *(.initcallearly.init) __early_initcall_end = .; *(.initcall0.init) *(.initcall0s.init) *(.initcall1.init) *(.initcall1s.init) *(.initcall2.init) *(.initcall2s.init) *(.initcall3.init) *(.initcall3s.init) *(.initcall4.init) *(.initcall4s.init) *(.initcall5.init) *(.initcall5s.init) *(.initcallrootfs.init) *(.initcall6.init) *(.initcall6s.init) *(.initcall7.init) *(.initcall7s.init)
   __initcall_end = .;
   }
以及do_initcalls:
static void __init do_initcalls(void)
{
initcall_t *call;
for (call = __initcall_start; call < __initcall_end; call++)
do_one_initcall(*call);
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
那么就不难理解阁下模块中的module_init中的初始化函数何时被调用了:在系统启动过程中start_kernel()->rest_init()->kernel_init()->do_basic_setup()->do_initcalls()。

 

 
 
  




2.在MODULE被定义的情况下(大部分可动态加载的driver模块都属于此, obj-m),module_init定义如下:
#define module_init(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
int init_module(void) __attribute__((alias(#initfn)));
这段宏定义关键点是后面一句,通过alias将initfn变名为init_module。前面那个__inittest的定义其实是种技巧,用来对initfn进行某种静态的类型检查,如果阁下将模块初始化函数定义成,比如,void gpio_init(void)或者是int gpio_init(int),那么在编译时都会有类似下面的warning:
GPIO/fsl-gpio.c: In function '__inittest':
GPIO/fsl-gpio.c:46: warning: return from incompatible pointer type
通过module_init将模块初始化函数统一别名为init_module,这样以后insmod时候,在系统内部会调用sys_init_module()去找到init_module函数的入口地址。
如果objdump -t gpio.ko,就会发现init_module和gpio_init位于相同的地址偏移处。简言之,这种情况下模块的初始化函数在insmod时候被调用。

解决c/c++ Error: redefinition of ‘xxx’ 的问题 ReplyInfo的。 阅读详情

相关推荐

矿卡CMP 170HX的AI推理性能优化实战

GPU计算在现代AI推理中扮演着核心角色,其并行计算架构特别适合处理神经网络的大规模矩阵运算。通过CUDA指令集优化和计算管线重构,可以显著提升硬件利用率,这在边缘计算和带宽敏感型任务中尤为重要。以NVIDIA CMP 170HX矿卡为例,通过禁用FMA指令和框架适配优化,其FP32性能可提升15.9倍,在Qwen2.5-1.5B模型的4-bit量化推理中达到A100同架构78%的解码速度。这种优化技术不仅让淘汰矿卡重获新生,更为边缘AI部署提供了高性价比解决方案,特别适合7B以下量化模型部署和多路视频分析

weixin_30432579的博客 624

[Linux driver]解密module_init

在Linux底下写过driver模块的对这个宏一定不会陌生。module_init宏在MODULE宏有没有定义的情况下展开的内容是不同的,如果这个宏没有定义,基本上表明阁下的模块是要编译进内核的(obj-y)。 1.在MODULE没有定义这种情况下,module_init定义如下: #define module_init(x)        __initcall(x); 因为 #def

embedded_man2011 技术空间 1295

使用fluent计算流噪声_Fluent能够做的事

刚接触到fluent的同学们,应该会比较好奇,fluent能够做些什么事情,和你的研究有没有关联,能不能达到你的目的?如果不弄明白这样一点,前期可能会做很多无用功。 fluent是计算流体力学的软件,是一个工具。这样一个工具发展至今,可以用来模拟的绝不只有流体力学。下面我们依次来说明。首先是流动,fluent提供了非常丰富的流动模型,不仅可以模拟层流,同样还可以模拟...

weixin_28717647的博客 4856

编译内核模块常见问题

在x86上做出来了,但是在ARM上却出现了很多问题,有内核代码准备的问题,有模块代码问题,也有Makefile的问题。看似不起眼的角色,出了问题也很纠结。 第一种:内核代码没有准备好 [root@localhost module]# make make -C /opt/kangear/kernel/linux-2.6.32.2 M=/root/桌面/kangear/module modu

Android/Linux的专栏 2万+

细胞膜电学特性的分数阶微积分建模

分数阶微积分在细胞膜电学特性建模中的应用主要体现在对细胞膜的电容行为和神经元放电活动的更精确描述上。

冰河世纪20的博客 619

数字麦克风PDM信号采集与STM32 I2S接口应用(二)

在使用STM32的数字麦克风I2S接口时,计算采样率让人头疼,芯片手册上没有明确的说法,而手册上的计算方法经过测试却和实验不符。借助搜索引擎,大部分资料都是来自于开发板卖家或开发板论坛,主要是咪头采集然后配置WM89系列解码芯片,然后配合FatFS、MP3解码等模式,主要是讲解I2S录音、存储、放音等。外文资料得到的也寥寥无几,也没有找到讲解STM32数字麦克风配置、计算的文档。加上网上资料转载、抄袭、浅尝辄止的笔记教程,这些更是让检索大海捞针,过程艰辛一言难尽,有些网文三言两语抑或作者都没有搞清楚随手一写

XIAOYOUDUODUO的博客 6053

错误

1、下述编写了一个模块,其中有一个中断函数,当内核接收到某个IRQ上的一个中断时会调用它。 其中注意第23行和第35行,init和exit前面均为两个英文下划线 "__"。详见http://www.kerneltravel.net/?p=86 #include<linux/module.h> #include<linux/init.h> #include<li...

weixin_34128501的博客 513

全球尺度遥感云计算平台:Google Earth Engine

Google Earth Engine(GEE)是一个基于 Google 云服务基础设施的遥感大数据分析平台,它结合 Google 强大的云计算能力与 NASA、ESA、NOAA 等机构的空间数据,用于在全球尺度解决一些非常重要的社会问题:森林退化、粮食安全、灾害预警、水资源管理、气候监测以及环境保护等。 GEE 官方宣传视频(版权归 Google 所有) Spacefan 的视频 ·303播放 发展背景 2008 年,手握 40 多年 LandSat 数据的美国地质调查局(USG...

qq_41240287的博客 5013

解密module_init,module_exit

include/linux/init.h 在Linux底下写过driver模块的对这个宏一定不会陌生。module_init宏在MODULE宏有没有定义的情况下展开的内容是不同的,如果这个宏没有定义,基本上表明阁下的模块是要编译进内核的(obj-y)。 1.在MODULE没有定义这种情况下,module_init定义如下: #define module_init(x) __i

be happy 1961

用友u8服务器优化,用友U8erp软件运行的性能优化方案图文教程

今天一定要给大家分享一下用友U8erp软件运行的性能优化方案图文教程,以下方案来自用友软件官方维护工程师反馈在在处理客户问题的时候,有一类问题较为挠头,就是诸如用友U8服务器效率低下的问题。比如用友U8运行慢,卡住等,我们暂先不提用友U8软件代码、脚本层面本身的性能提升问题,我们只是基于现有用友U8软件版本,在客户现有环境下排查用友U8软件运行的性能瓶颈,并采取一定的技术手段进行性能调校。本文将推...

weixin_39882870的博客 5306

【GlobalMapper精品教程】074:从Lidar点云创建3D地形模型

本文基于地形点云数据,基于泊松方法、贪婪三角形测量方法和阿尔法形状创建3d地形模型。

智慧空间实验室 2164

解密module_init幕后的故事

解密module_init幕后的故事 在Linux底下写过driver模块的对这个宏一定不会陌生。module_init宏在MODULE宏有没有定义的情况下展开的内容是不同的,如果这个宏没有定义,基本上表明阁下的模块是要编译进内核的(obj-y)。 1.在MODULE没有定义这种情况下,module_init定义如下: #define module_init(x)        __

海纳百川 723

基于YOLOv11与相机标定的齿轮尺寸测量系统

本文详细介绍了一种基于深度学习的目标检测算法YOLOv11与相机标定技术相结合的齿轮尺寸自动测量系统。该系统能够实时检测图像中的齿轮目标,并精确测量其关键尺寸参数,包括齿顶圆直径、齿根圆直径、模数等。我们构建了完整的深度学习解决方案,包含数据采集与标注、模型训练、相机标定、尺寸测量算法以及用户友好的UI界面。本文提供了完整的代码实现,并推荐了相关的参考数据集,为工业视觉检测领域提供了实用的技术方案。关键词:YOLOv11;齿轮检测;尺寸测量;相机标定;深度学习;工业视觉python。

YOLO 411
上一篇: EPOLL学习
下一篇: NPAPI & NPRuntime 簡介 Scriptable Plugin
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值