Linux独立模块如何使用struct mnt_namespace 结构体

在Linux内核中,struct mnt_namespace 用于管理挂载命名空间(Mount Namespace),它是实现容器文件系统隔离的核心结构。以下是使用该结构体的关键步骤和示例:


1. 关键结构体成员

1
2
3
4
5
6
7
8
struct mnt_namespace {
atomic_t count; // 引用计数
struct mount * root; // 根挂载点
struct list_head list; // 挂载点链表头
wait_queue_head_t poll; // 等待队列
u64 seq; // 序列号(用于事件通知)
// ... 其他成员(版本相关)
};

2. 使用场景

  • 获取当前命名空间
    通过当前进程的 nsproxy 获取:

    1
    struct mnt_namespace *ns = current->nsproxy->mnt_ns;
  • 创建新命名空间
    克隆时使用 CLONE_NEWNS 标志(需调用 copy_mnt_ns()):

    1
    struct nsproxy *new_nsp = create_new_namespaces(CLONE_NEWNS, ...);
  • 遍历挂载点
    访问命名空间中的所有挂载点:

    1
    2
    3
    4
    struct mount *mnt;
    list_for_each_entry(mnt, &ns->list, mnt_list) {
    // 操作 mnt
    }

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
#include <linux/module.h>
#include <linux/nsproxy.h>
#include <linux/mount.h>
#include <linux/seq_file.h> // seq_path

static void print_mountpoints(struct mnt_namespace *ns) {
struct mount *mnt;

// 必须加锁防止并发修改
down_read(&namespace_sem);
list_for_each_entry(mnt, &ns->list, mnt_list) {
struct path root_path = { .mnt = &mnt->mnt, .dentry = mnt->mnt.mnt_root };
char *pathname = kmalloc(PATH_MAX, GFP_KERNEL);

if (pathname) {
// 获取挂载点路径
seq_path(pathname, &root_path, " \t\n");
pr_info("Mount: %s\n", pathname);
kfree(pathname);
}
}
up_read(&namespace_sem);
}

static int __init my_module_init(void) {
struct mnt_namespace *ns = current->nsproxy->mnt_ns;
get_mnt_ns(ns); // 增加引用计数
print_mountpoints(ns);
put_mnt_ns(ns); // 减少引用计数
return 0;
}

module_init(my_module_init);
MODULE_LICENSE("GPL");

4. 注意事项

  • 引用计数管理

    • 使用 get_mnt_ns() 增加引用。
    • 使用 put_mnt_ns() 减少引用(防止内存泄漏)。
  • 同步锁
    操作 list 链表时需持有 namespace_sem 信号量(读锁用 down_read(), 写锁用 down_write())。

  • 内核版本差异
    不同内核版本中结构体可能变化(如 v5.10+ 引入 ns->mounts 代替 list),需参考对应版本的源码。


5. 典型应用

  • 容器运行时:为每个容器创建独立的挂载命名空间。
  • 文件系统隔离:在 unshare(CLONE_NEWNS)setns() 中操作命名空间。
  • 挂载点监控:通过遍历 ns->list 实时跟踪挂载变化。

提示:操作内核结构需谨慎!确保代码符合目标内核版本,并在开发环境中充分测试。