module_init()

本文详细介绍了通过module_init()注册的模块初始化过程。这些模块在内核启动时按链接顺序依次调用,仅在内核初始化期间生效。文章还讨论了模块间的调用顺序及其实际意义。

通过module_init()注册的模块初始化部分是在init()->do_basic_setup()->do_initcalls()中被依次调用的,这么初始化函数只是在内核初始化的时候被调用,之后内核释放其空间。所以准确的说不应该是“调度”。
被调用的次序是由注册的顺序决定的,依靠该初始化函数在initcall_t表中的先后位置,也就是说在链接阶段各个模块链接到内核的顺序。
被调用的先后顺序应该没有必要关心,各个模块之间应该没有什么关系吧,因为在此之前,已经建立了内核基本运行环境。

下载前必看:https://pan.quark.cn/s/a4b39357ea24 在本资料中,将阐述如何运用JavaScript达成单击下拉列表框选定选项后即时转向对应页面的功能。 此种技术适用于网页布局中用户需迅速选取并转向不同页面的情形,诸如网站导航栏或内容目录等场景。 达成此功能,能够显著改善用户交互体验,精简用户的操作流程。 我们须熟悉HTML里的`<select>`组件,该组件用于构建一个选择列表。 用户可从中选定一项,并可引发一个事件来响应用户的这一选择动作。 在本次实例中,我们借助`onchange`事件监听器来实现当用户在下拉列表框中选定某个选项时,页面能自动转向该选项关联的链接地址。 JavaScript里的`window.location`属性旨在获取或设定浏览器当前载入页面的网址,通过变更该属性的值,能够实现页面的转向。 在本次实例的实现方案里,运用了`eval()`函数来动态执行字符串表达式,这在现代的JavaScript开发实践中通常不被推荐使用,因为它可能诱发安全问题及难以排错的错误。 然而,为了本例的简化展示,我们暂时搁置这一问题,因为在更复杂的实际应用中,可选用其他方法,例如ES6中的模板字符串或其他函数来安全地构建和执行字符串。 具体到本例的代码实现,`MM_jumpMenu`函数负责处理转向逻辑。 它接收三个参数:`targ`、`selObj`和`restore`。 其中`targ`代表要转向的页面,`selObj`是触发事件的下拉列表框对象,`restore`是标志位,用以指示是否需在转向后将下拉列表框的选项恢复至默认的提示项。 函数的实现通过获取`selObj`中当前选定的`selectedIndex`对应的`value`属性值,并将其赋予`...
### 后期初始化函数 `later_init` 和模块初始化函数 `module_init` 在 Linux 内核开发中,`later_init` 并不是一个标准的术语或宏定义,但它可能指的是某些特定场景下的后期初始化逻辑。而 `module_init` 是一个广泛使用的宏,用于指定模块加载时执行的入口函数。 #### 1. **`module_init` 宏** `module_init` 是一种机制,允许开发者为内核模块指定一个初始化函数,在模块被加载到内核时自动调用该函数。其核心实现依赖于 GCC 的属性扩展功能 (`__attribute__((constructor))`) 或类似的链接器脚本技术[^4]。 以下是 `module_init` 的基本工作原理: - 当编译带有 `module_init(init_function)` 的代码时,`init_function` 被标记为需要优先运行的函数之一。 - 在模块加载过程中,内核会扫描这些特殊标记的函数并依次调用它们。 示例代码如下: ```c #include <linux/module.h> #include <linux/kernel.h> static int __init my_module_init(void) { printk(KERN_INFO "Module initialized\n"); return 0; } static void __exit my_module_exit(void) { printk(KERN_INFO "Module exited\n"); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); ``` 上述代码中的 `my_module_init` 函数会在模块加载时被执行。 --- #### 2. **假设的 `later_init` 场景** 虽然没有官方文档提及名为 `later_init` 的具体概念,但在实际项目中可能存在类似的功能需求。例如,有些驱动程序或子系统希望延迟部分初始化操作直到更晚的时间点完成(比如等待其他组件准备好)。这种情况下可以手动设计类似于 `later_init` 的机制。 常见的做法包括但不限于以下几种方式: - 使用定时器接口(如 `timer_setup()`),安排某个延后的回调函数; - 利用工作队列(workqueue)提交异步任务; - 借助设备模型框架的通知链表监听事件触发条件满足后再继续处理剩余步骤; 下面是一个简单的例子展示如何通过 workqueue 实现所谓的 “late init” 功能: ```c #include <linux/workqueue.h> #include <linux/init.h> #include <linux/module.h> struct delayed_work my_late_init_work; void late_init_handler(struct work_struct *work) { pr_info("Late initialization completed.\n"); } DECLARE_DELAYED_WORK(my_late_init_work, late_init_handler); static int __init early_init(void){ queue_delayed_work(system_wq,&my_late_init_work,msecs_to_jiffies(500)); pr_info("Early initialization done, scheduling late init...\n"); return 0; } static void __exit cleanup_mod(void){ cancel_delayed_work_sync(&my_late_init_work); pr_info("Cleanup complete.\n"); } module_init(early_init); module_exit(cleanup_mod); MODULE_LICENSE("Dual BSD/GPL"); ``` 在这个案例里,“早起”的初始化由 `early_init` 执行完毕后立即调度了一个延迟作业去稍候再做额外的工作——即所谓“晚期”。 --- #### 3. **两者的对比** | 特性 | `module_init` | 自定义 `later_init` | |--------------------------|--------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------| | 初始化时机 | 模块载入瞬间 | 可设定任意时间间隔 | | 是否内置支持 | 是 | 需要自行构建 | | 应用范围 | 主要用作模块启动阶段的核心配置 | 更适合那些需分多阶段逐步完善的复杂对象 | 需要注意的是,如果确实存在某种形式的标准 API 名叫 `later_init`,那么它应该属于某特定领域或者第三方补丁集的一部分而不是原生Linux Kernel所提供. --- ### 结论 综上所述,尽管两者都涉及到了系统的初始化过程,但是他们针对的应用场合以及具体的运作模式存在着明显的差异。对于常规意义上的插件化管理来说推荐采用成熟的 `module_init`;而对于更加精细控制的需求则考虑引入自定义方案诸如基于WorkQueue等手段达成目的。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值