解密module_init幕后的故事

本文深入解析了Linux环境下module_init宏的工作原理及其实现细节。详细介绍了该宏在不同定义情况下的展开过程,以及如何通过链接脚本和初始化函数实现模块加载。

在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()。

 

(转自http://www.embexperts.com/viewthread.php?tid=39)

 

 

### 代码功能与作用解释 以下是对代码中涉及的函数和参数的功能与作用进行详细说明: #### 1. `base64_decode` `base64_decode` 是 PHP 中用于解码 Base64 编码字符串的函数。在加密和解密过程中,Base64 编码通常用于将二进制数据转换为文本格式以便于传输或存储。在这里,`$encrypted` 是一个经过 Base64 编码的加密字符串,通过调用 `base64_decode` 将其还原为原始的二进制数据[^1]。 ```php $ciphertext_dec = base64_decode($encrypted); ``` #### 2. `mcrypt_module_open` `mcrypt_module_open` 用于打开一个对称加密模块。它需要四个参数: - 第一个参数指定加密算法,在这里是 `MCRYPT_RIJNDAEL_128`,表示使用 AES-128 加密算法。 - 第二个参数是描述符(通常是空字符串),用于指定库路径。 - 第三个参数指定加密模式,在这里是 `MCRYPT_MODE_CBC`,表示使用 CBC(Cipher Block Chaining)模式。 - 第四个参数是初始化向量(IV)的描述符。 该函数返回一个模块资源,供后续操作使用[^1]。 ```php $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); ``` #### 3. 初始化向量(IV) 初始化向量(IV)是一个固定长度的随机值,用于增加加密的安全性。在 CBC 模式下,IV 是必需的。这里从 `$this->key` 中提取前 16 字节作为 IV,因为 AES-128 的块大小为 16 字节。 ```php $iv = substr($this->key, 0, 16); ``` #### 4. `mcrypt_generic_init` `mcrypt_generic_init` 用于初始化加密模块。它需要三个参数: - 第一个参数是通过 `mcrypt_module_open` 返回的模块资源。 - 第二个参数是加密密钥。 - 第三个参数是初始化向量(IV)。 初始化完成后,模块可以用于解密或加密数据。 ```php mcrypt_generic_init($module, $this->key, $iv); ``` #### 5. `mdecrypt_generic` `mdecrypt_generic` 是实际执行解密操作的函数。它接受两个参数: - 第一个参数是通过 `mcrypt_module_open` 返回的模块资源。 - 第二个参数是要解密的数据。 该函数返回解密后的明文数据。 ```php $decrypted = mdecrypt_generic($module, $ciphertext_dec); ``` #### 6. 资源释放 `mcrypt_generic_deinit` 和 `mcrypt_module_close` 分别用于释放加密模块的初始化状态和关闭模块资源,以避免内存泄漏[^1]。 ```php mcrypt_generic_deinit($module); mcrypt_module_close($module); ``` --- ### 完整代码功能总结 这段代码的主要功能是对一段经过 AES-128-CBC 加密并 Base64 编码的字符串进行解密。具体步骤如下: 1. 使用 `base64_decode` 将 Base64 编码的加密字符串转换为二进制数据。 2. 打开一个 AES-128-CBC 加密模块。 3. 提取初始化向量(IV)并初始化加密模块。 4. 使用 `mdecrypt_generic` 对加密数据进行解密。 5. 释放模块资源以完成操作。 --- ### 注意事项 由于 `mcrypt` 扩展从 PHP 7.1 开始被废弃,并在 PHP 7.2 中完全移除,因此在较新的 PHP 版本中无法直接使用上述代码。可以通过安装扩展或改用 `openssl` 函数来实现相同功能[^2]。 以下是使用 `openssl` 替代的示例代码: ```php function decryptData($encrypted, $key) { $iv = substr($key, 0, 16); // 提取 IV $ciphertext_dec = base64_decode($encrypted); // 解码 Base64 $decrypted = openssl_decrypt($ciphertext_dec, 'AES-128-CBC', $key, 0, $iv); // 解密 return $decrypted; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值