query_module系统调用及示例

query_module 函数详解

  1. 函数介绍

query_module 是 Linux 系统中用于查询内核模块信息的系统调用。可以把内核模块想象成”系统功能的插件”——就像你可以为浏览器安装插件来扩展功能一样,Linux 内核也可以通过加载不同的模块来扩展功能。

data-ad-format="fluid" data-ad-layout-key="-7k+ex-4a-9w+4a">

query_module 就像一个”模块信息查询器”,它允许你查看系统中已加载的内核模块的详细信息,包括模块名称、引用计数、依赖关系等。

  1. 函数原型
1
2
3
4
5
#include <linux/module.h>

int query_module(const char *name, int which, void *buf,
size_t bufsize, size_t *ret);

  1. 功能

query_module 函数用于查询内核模块的各种信息。它可以获取模块列表、模块引用计数、模块符号信息、模块依赖关系等。

  1. 参数
  • name: 要查询的模块名称(NULL 表示查询所有模块)

  • which: 查询类型(指定要获取的信息类型)

  • buf: 指向缓冲区的指针,用于存储返回的信息

  • bufsize: 缓冲区大小

  • ret: 指向返回值的指针

  1. 查询类型(which 参数)

类型值说明QM_MODULES1获取模块名称列表QM_REFS2获取模块引用计数QM_SYMBOLS3获取模块符号信息QM_INFO4获取模块详细信息QM_MODINFO5获取模块信息(新版本)

  1. module_info 结构体
1
2
3
4
5
6
7
8
struct module_info {
unsigned long addr; /* 模块地址 */
unsigned long size; /* 模块大小 */
unsigned long flags; /* 模块标志 */
long refcnt; /* 引用计数 */
unsigned char usecount; /* 使用计数 */
};

  1. 返回值
  • 成功: 返回 0

  • 失败: 返回 -1,并设置相应的 errno 错误码

  1. 常见错误码
  • EPERM: 权限不足(通常需要 root 权限)

  • EINVAL: 参数无效

  • ENOENT: 指定的模块不存在

  • ENOMEM: 内存不足

  • EFAULT: 参数指针无效

  • ENOSYS: 系统不支持此调用

  1. 相似函数或关联函数
  • lsmod: 命令行工具列出模块

  • insmod: 加载内核模块

  • rmmod: 卸载内核模块

  • modprobe: 智能加载内核模块

  • /proc/modules: 模块信息文件

  • /sys/module/: 模块 sysfs 接口

  • kmod: 内核模块管理工具

  1. 示例代码

示例1:基础用法 - 查询模块列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/module.h>
#include <errno.h>
#include <string.h>

// 注意:query_module 在现代 Linux 系统中可能不可用
// 这里提供概念性示例和现代替代方案

int main() {
printf("=== query_module 基础示例 ===\n\n");

printf("注意: query_module 是已废弃的系统调用\n");
printf("在现代 Linux 系统中通常不可用\n\n");

printf("功能说明:\n");
printf("query_module 用于查询内核模块信息:\n");
printf("1. QM_MODULES: 获取模块名称列表\n");
printf("2. QM_REFS: 获取模块引用计数\n");
printf("3. QM_SYMBOLS: 获取模块符号信息\n");
printf("4. QM_INFO: 获取模块详细信息\n");
printf("5. QM_MODINFO: 获取模块信息(新版本)\n");

printf("\n=== 现代替代方案 ===\n");
printf("1. 使用 /proc/modules 文件\n");
printf("2. 使用 lsmod 命令\n");
printf("3. 使用 modinfo 命令\n");
printf("4. 使用 /sys/module/ 接口\n");

return 0;
}

示例2:现代替代方案 - 模块信息查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>

// 通过 /proc/modules 获取模块信息
int get_modules_via_proc() {
printf("=== 通过 /proc/modules 获取模块信息 ===\n");

FILE *fp = fopen("/proc/modules", "r");
if (!fp) {
perror("打开 /proc/modules 失败");
return -1;
}

printf("%-25s %-10s %-8s %-15s %s\n",
"模块名称", "大小", "使用数", "被谁使用", "状态");
printf("%-25s %-10s %-8s %-15s %s\n",
"--------", "----", "----", "------", "----");

char line&#91;512];
int count = 0;

while (fgets(line, sizeof(line), fp) && count < 20) {
char module_name&#91;64];
unsigned long size;
int use_count;
char used_by&#91;256];
char status&#91;32];
char address&#91;32];

// 解析 /proc/modules 格式
int parsed = sscanf(line, "%63s %lu %d %255s %31s %31s",
module_name, &size, &use_count, used_by, status, address);

if (parsed >= 4) {
printf("%-25s %-10lu %-8d %-15s %s\n",
module_name, size, use_count, used_by,
parsed >= 5 ? status : "-");
count++;
}
}

fclose(fp);

if (count == 0) {
printf("没有模块信息\n");
} else {
printf("\n显示了前 %d 个模块\n", count);
}

return 0;
}

// 通过 /sys/module/ 获取模块详细信息
int get_module_details_via_sysfs() {
printf("\n=== 通过 /sys/module/ 获取模块详细信息 ===\n");

// 检查 /sys/module/ 目录
if (access("/sys/module", F_OK) != 0) {
printf("系统不支持 /sys/module/ 接口\n");
return -1;
}

// 列出几个模块的详细信息
const char *modules&#91;] = {"usbcore", "tcp", "ext4", "loop", NULL};

for (int i = 0; modules&#91;i]; i++) {
char module_path&#91;256];
snprintf(module_path, sizeof(module_path), "/sys/module/%s", modules&#91;i]);

if (access(module_path, F_OK) == 0) {
printf("\n模块: %s\n", modules&#91;i]);

// 检查模块参数
char param_path&#91;256];
snprintf(param_path, sizeof(param_path), "%s/parameters", module_path);
if (access(param_path, F_OK) == 0) {
printf(" ✓ 支持参数配置\n");
}

// 检查模块引用
char refcnt_path&#91;256];
snprintf(refcnt_path, sizeof(refcnt_path), "%s/refcnt", module_path);
FILE *refcnt_fp = fopen(refcnt_path, "r");
if (refcnt_fp) {
char refcnt&#91;32];
if (fgets(refcnt, sizeof(refcnt), refcnt_fp)) {
printf(" 引用计数: %s", refcnt);
}
fclose(refcnt_fp);
}

// 检查模块状态
char initstate_path&#91;256];
snprintf(initstate_path, sizeof(initstate_path), "%s/initstate", module_path);
FILE *initstate_fp = fopen(initstate_path, "r");
if (initstate_fp) {
char initstate&#91;32];
if (fgets(initstate, sizeof(initstate), initstate_fp)) {
printf(" 初始化状态: %s", initstate);
}
fclose(initstate_fp);
}
}
}

return 0;
}

// 模拟 query_module 功能
void simulate_query_module() {
printf("\n=== 模拟 query_module 功能 ===\n");

printf("QM_MODULES (获取模块列表):\n");
printf(" 模块1: usbcore\n");
printf(" 模块2: tcp\n");
printf(" 模块3: ext4\n");
printf(" 模块4: loop\n");
printf(" 模块5: sd_mod\n");

printf("\nQM_INFO (获取模块详细信息):\n");
printf(" 模块名称: usbcore\n");
printf(" 地址: 0xffffffffc0000000\n");
printf(" 大小: 123456 字节\n");
printf(" 引用计数: 5\n");
printf(" 状态: Live\n");

printf("\nQM_REFS (获取引用计数):\n");
printf(" usbcore: 5\n");
printf(" tcp: 3\n");
printf(" ext4: 2\n");
printf(" loop: 1\n");

printf("\nQM_SYMBOLS (获取符号信息):\n");
printf(" usb_register: 0xffffffffc0001000\n");
printf(" usb_deregister: 0xffffffffc0002000\n");
printf(" usb_submit_urb: 0xffffffffc0003000\n");
}

int main() {
printf("=== 内核模块查询系统 ===\n\n");

// 显示系统信息
printf("系统信息:\n");
printf(" 用户 ID: %d\n", getuid());
printf(" 进程 ID: %d\n", getpid());

// 检查权限
if (getuid() != 0) {
printf(" 注意: 某些模块信息需要 root 权限\n");
}
printf("\n");

// 通过 /proc/modules 获取信息
get_modules_via_proc();

// 通过 /sys/module/ 获取详细信息
get_module_details_via_sysfs();

// 模拟 query_module 功能
simulate_query_module();

printf("\n=== 现代模块管理工具 ===\n");
printf("常用的模块管理命令:\n");
printf("1. lsmod # 列出已加载模块\n");
printf("2. modinfo module # 显示模块信息\n");
printf("3. insmod module.ko # 加载模块\n");
printf("4. rmmod module # 卸载模块\n");
printf("5. modprobe module # 智能加载模块\n");
printf("6. depmod # 生成模块依赖\n");
printf("\n");

printf("模块信息文件:\n");
printf("1. /proc/modules # 已加载模块列表\n");
printf("2. /proc/devices # 设备号信息\n");
printf("3. /sys/module/ # 模块 sysfs 接口\n");
printf("4. /lib/modules/ # 模块文件目录\n");

return 0;
}

示例3:完整的模块管理工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>

// 配置结构体
struct module_config {
int list_modules; // 列出模块
int show_details; // 显示详细信息
int verbose; // 详细输出
int show_refs; // 显示引用计数
int show_symbols; // 显示符号信息
char *module_name; // 指定模块名称
char *search_pattern; // 搜索模式
};

// 模块信息结构体
struct module_info {
char name&#91;256];
unsigned long size;
int ref_count;
char used_by&#91;512];
char status&#91;32];
unsigned long address;
};

// 通过 /proc/modules 解析模块信息
int parse_proc_modules(struct module_info *modules, int max_modules) {
FILE *fp = fopen("/proc/modules", "r");
if (!fp) {
return -1;
}

int count = 0;
char line&#91;1024];

while (fgets(line, sizeof(line), fp) && count < max_modules) {
struct module_info *mod = &modules&#91;count];
char extra&#91;512];

// 解析 /proc/modules 格式
int parsed = sscanf(line, "%255s %lu %d %511s %31s %31s",
mod->name, &mod->size, &mod->ref_count,
mod->used_by, mod->status, extra);

if (parsed >= 4) {
count++;
}
}

fclose(fp);
return count;
}

// 显示模块列表
void show_module_list(struct module_info *modules, int count,
const struct module_config *config) {
printf("=== 内核模块列表 ===\n");
printf("%-25s %-12s %-8s %-20s %s\n",
"模块名称", "大小", "引用数", "被谁使用", "状态");
printf("%-25s %-12s %-8s %-20s %s\n",
"--------", "----", "----", "------", "----");

int displayed = 0;
for (int i = 0; i < count && displayed < 50; i++) {
struct module_info *mod = &modules&#91;i];

// 如果指定了搜索模式,进行过滤
if (config->search_pattern) {
if (strstr(mod->name, config->search_pattern) == NULL) {
continue;
}
}

// 如果指定了模块名称,精确匹配
if (config->module_name) {
if (strcmp(mod->name, config->module_name) != 0) {
continue;
}
}

printf("%-25s %-12lu %-8d %-20s %s\n",
mod->name, mod->size, mod->ref_count,
mod->used_by, mod->status);
displayed++;
}

if (displayed == 0) {
printf("没有找到匹配的模块\n");
} else if (displayed < count) {
printf("\n显示了 %d 个匹配模块 (总共 %d 个)\n", displayed, count);
}
}

// 显示模块详细信息
void show_module_details(struct module_info *modules, int count,
const struct module_config *config) {
printf("\n=== 模块详细信息 ===\n");

int found = 0;
for (int i = 0; i < count; i++) {
struct module_info *mod = &modules&#91;i];

// 检查是否匹配
if (config->module_name) {
if (strcmp(mod->name, config->module_name) != 0) {
continue;
}
} else if (config->search_pattern) {
if (strstr(mod->name, config->search_pattern) == NULL) {
continue;
}
}

printf("\n模块: %s\n", mod->name);
printf(" 大小: %lu 字节 (%.2f KB)\n", mod->size, (double)mod->size / 1024);
printf(" 引用计数: %d\n", mod->ref_count);
printf(" 被谁使用: %s\n", mod->used_by);
printf(" 状态: %s\n", mod->status);

// 显示 sysfs 信息
char sysfs_path&#91;256];
snprintf(sysfs_path, sizeof(sysfs_path), "/sys/module/%s", mod->name);

if (access(sysfs_path, F_OK) == 0) {
printf(" Sysfs 路径: %s\n", sysfs_path);

// 检查参数
char param_path&#91;256];
snprintf(param_path, sizeof(param_path), "%s/parameters", sysfs_path);
if (access(param_path, F_OK) == 0) {
printf(" ✓ 支持运行时参数配置\n");
}

// 检查引用计数
char refcnt_path&#91;256];
snprintf(refcnt_path, sizeof(refcnt_path), "%s/refcnt", sysfs_path);
FILE *refcnt_fp = fopen(refcnt_path, "r");
if (refcnt_fp) {
char refcnt&#91;32];
if (fgets(refcnt, sizeof(refcnt), refcnt_fp)) {
printf(" 当前引用计数: %s", refcnt);
}
fclose(refcnt_fp);
}
}

found++;
if (config->module_name) {
break; // 只显示指定模块
}

if (found >= 5) {
printf("\n只显示前 5 个匹配模块的详细信息\n");
break;
}
}

if (found == 0) {
if (config->module_name) {
printf("未找到模块: %s\n", config->module_name);
} else if (config->search_pattern) {
printf("未找到匹配模式 '%s' 的模块\n", config->search_pattern);
} else {
printf("没有模块信息\n");
}
}
}

// 显示系统模块统计
void show_module_statistics(struct module_info *modules, int count) {
printf("\n=== 模块统计信息 ===\n");
printf("总模块数: %d\n", count);

if (count > 0) {
// 统计引用计数
int total_refs = 0;
int max_refs = 0;
int zero_refs = 0;
unsigned long total_size = 0;

for (int i = 0; i < count; i++) {
total_refs += modules&#91;i].ref_count;
total_size += modules&#91;i].size;

if (modules&#91;i].ref_count > max_refs) {
max_refs = modules&#91;i].ref_count;
}

if (modules&#91;i].ref_count == 0) {
zero_refs++;
}
}

printf("总大小: %.2f MB\n", (double)total_size / (1024 * 1024));
printf("平均引用计数: %.2f\n", (double)total_refs / count);
printf("最大引用计数: %d\n", max_refs);
printf("零引用模块数: %d\n", zero_refs);

// 显示最常见的模块
printf("\n最常用的模块:\n");
int shown = 0;
for (int i = 0; i < count && shown < 5; i++) {
if (modules&#91;i].ref_count > 0) {
printf(" %s (%d 引用)\n", modules&#91;i].name, modules&#91;i].ref_count);
shown++;
}
}
}
}

// 显示帮助信息
void show_help(const char *program_name) {
printf("用法: %s &#91;选项]\n", program_name);
printf("\n选项:\n");
printf(" -l, --list 列出所有模块\n");
printf(" -d, --details 显示模块详细信息\n");
printf(" -r, --refs 显示引用计数\n");
printf(" -n, --name=MODULE 指定模块名称\n");
printf(" -s, --search=PATTERN 搜索模块名称\n");
printf(" -v, --verbose 详细输出\n");
printf(" -S, --statistics 显示统计信息\n");
printf(" -h, --help 显示此帮助信息\n");
printf("\n示例:\n");
printf(" %s -l # 列出所有模块\n", program_name);
printf(" %s -d -n usbcore # 显示 usbcore 模块详细信息\n", program_name);
printf(" %s -l -s usb # 列出包含 usb 的模块\n", program_name);
printf(" %s -S # 显示模块统计信息\n", program_name);
printf(" %s -d -s network # 显示网络相关模块详情\n", program_name);
}

int main(int argc, char *argv&#91;]) {
struct module_config config = {
.list_modules = 0,
.show_details = 0,
.verbose = 0,
.show_refs = 0,
.show_symbols = 0,
.module_name = NULL,
.search_pattern = NULL
};

printf("=== 内核模块查询工具 ===\n\n");

// 解析命令行参数
static struct option long_options&#91;] = {
{"list", no_argument, 0, 'l'},
{"details", no_argument, 0, 'd'},
{"refs", no_argument, 0, 'r'},
{"symbols", no_argument, 0, 'y'},
{"name", required_argument, 0, 'n'},
{"search", required_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
{"statistics", no_argument, 0, 'S'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};

int opt;
while ((opt = getopt_long(argc, argv, "ldryn:s:vSh", long_options, NULL)) != -1) {
switch (opt) {
case 'l':
config.list_modules = 1;
break;
case 'd':
config.show_details = 1;
break;
case 'r':
config.show_refs = 1;
break;
case 'y':
config.show_symbols = 1;
break;
case 'n':
config.module_name = optarg;
break;
case 's':
config.search_pattern = optarg;
break;
case 'v':
config.verbose = 1;
break;
case 'S':
config.list_modules = 1;
break;
case 'h':
show_help(argv&#91;0]);
return 0;
default:
fprintf(stderr, "使用 '%s --help' 查看帮助信息\n", argv&#91;0]);
return 1;
}
}

// 如果没有指定操作,默认列出模块
if (!config.list_modules && !config.show_details &&
!config.show_refs && !config.show_symbols) {
config.list_modules = 1;
}

// 显示系统信息
if (config.verbose) {
printf("系统信息:\n");
printf(" 用户 ID: %d\n", getuid());
printf(" 进程 ID: %d\n", getpid());
printf(" 当前目录: %s\n", getcwd(NULL, 0));
printf("\n");
}

// 读取模块信息
struct module_info modules&#91;500];
int module_count = parse_proc_modules(modules, 500);

if (module_count == -1) {
printf("错误: 无法读取模块信息\n");
printf("可能的原因:\n");
printf("1. 系统不支持 /proc/modules\n");
printf("2. 权限不足\n");
printf("3. 内核不支持模块\n");
return 1;
}

if (config.verbose) {
printf("读取到 %d 个模块\n\n", module_count);
}

// 执行相应操作
if (config.list_modules) {
show_module_list(modules, module_count, &config);
}

if (config.show_details) {
show_module_details(modules, module_count, &config);
}

if (optind == 1) { // 如果没有指定参数,显示统计信息
show_module_statistics(modules, module_count);
}

printf("\n=== 模块管理最佳实践 ===\n");
printf("模块安全建议:\n");
printf("1. 只加载可信的模块\n");
printf("2. 定期更新模块\n");
printf("3. 监控模块加载活动\n");
printf("4. 限制模块加载权限\n");
printf("5. 使用签名验证模块\n");
printf("\n");

printf("模块性能优化:\n");
printf("1. 卸载不用的模块\n");
printf("2. 优化模块参数\n");
printf("3. 监控模块内存使用\n");
printf("4. 使用模块黑名单\n");
printf("5. 合理配置模块依赖\n");
printf("\n");

printf("现代替代方案:\n");
printf("1. /proc/modules: 模块列表信息\n");
printf("2. /sys/module/: 模块 sysfs 接口\n");
printf("3. modinfo: 模块详细信息\n");
printf("4. lsmod: 列出模块\n");
printf("5. modprobe: 智能模块加载\n");
printf("6. rmmod: 卸载模块\n");

return 0;
}

编译和运行说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 编译示例程序
gcc -o query_module_example1 example1.c
gcc -o query_module_example2 example2.c
gcc -o query_module_example3 example3.c

# 运行示例
./query_module_example1
./query_module_example2
./query_module_example3 --help
./query_module_example3 -l
./query_module_example3 -d -n usbcore
./query_module_example3 -l -s usb
./query_module_example3 -S

系统要求检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 检查模块支持
ls /proc/modules
ls /sys/module/

# 检查模块工具
which lsmod
which modinfo
which modprobe
which rmmod

# 查看内核模块目录
ls /lib/modules/$(uname -r)/kernel/

# 检查内核配置
grep -i module /boot/config-$(uname -r)

重要注意事项

已废弃: query_module 在现代 Linux 系统中已废弃

权限要求: 某些模块信息需要 root 权限

系统依赖: 需要内核支持模块和相应的文件系统接口

错误处理: 始终检查返回值和 errno

兼容性: 不同内核版本可能有差异

实际应用场景

系统监控: 监控内核模块加载和卸载

安全审计: 审计系统中加载的模块

性能分析: 分析模块对系统性能的影响

故障诊断: 诊断模块相关的问题

自动化管理: 自动化模块管理脚本

现代替代方案详解

使用 /proc/modules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 读取模块列表
int read_module_list() {
FILE *fp = fopen("/proc/modules", "r");
if (!fp) return -1;

char line&#91;1024];
while (fgets(line, sizeof(line), fp)) {
char name&#91;256], used_by&#91;256], status&#91;32];
unsigned long size;
int ref_count;

if (sscanf(line, "%255s %lu %d %255s %31s",
name, &size, &ref_count, used_by, status) >= 4) {
printf("%-20s %8lu %3d %s\n", name, size, ref_count, used_by);
}
}

fclose(fp);
return 0;
}

使用 /sys/module/ 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 读取模块详细信息
int read_module_details(const char *module_name) {
char path&#91;256];

// 读取引用计数
snprintf(path, sizeof(path), "/sys/module/%s/refcnt", module_name);
FILE *fp = fopen(path, "r");
if (fp) {
char refcnt&#91;32];
if (fgets(refcnt, sizeof(refcnt), fp)) {
printf("引用计数: %s", refcnt);
}
fclose(fp);
}

return 0;
}

使用命令行工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 列出模块
lsmod

# 显示模块信息
modinfo module_name

# 加载模块
sudo modprobe module_name

# 卸载模块
sudo rmmod module_name

# 生成依赖关系
sudo depmod

最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 安全的模块信息查询函数
int safe_query_modules(struct module_info *modules, int max_count) {
// 验证参数
if (!modules || max_count <= 0) {
errno = EINVAL;
return -1;
}

// 检查文件存在性
if (access("/proc/modules", F_OK) != 0) {
errno = ENOENT;
return -1;
}

// 读取模块信息
return parse_proc_modules(modules, max_count);
}

// 模块安全检查
int validate_module_security(const char *module_name) {
// 检查模块名称合法性
if (!module_name || strlen(module_name) == 0) {
return -1;
}

// 检查是否在黑名单中
// 这里简化处理,实际应用中可以检查 /etc/modprobe.d/blacklist.conf
const char *blacklisted&#91;] = {"firewire-sbp2", "usbmouse", NULL};
for (int i = 0; blacklisted&#91;i]; i++) {
if (strcmp(module_name, blacklisted&#91;i]) == 0) {
printf("警告: 模块 '%s' 在黑名单中\n", module_name);
return -1;
}
}

return 0;
}

这些示例展示了 query_module 函数的概念以及现代 Linux 系统中查询内核模块信息的各种替代方案,帮助你全面了解 Linux 系统中的模块管理机制。

query_module系统调用及示例-CSDN博客

https://www.calcguide.tech/2025/08/28/query-module系统调用及示例/

data-ad-format="auto" data-full-width-responsive="true">