Linux 内核 6.1.x 加载内核模块时的虚拟内存遍历

问题描述 投票:0回答:1

目标: 对于指定进程(通过其 pid),确定分配的虚拟地址空间的大小(所有 vmas 的总和)。

问题:从内核 6.1 开始,vm_area_struct 中不存在 vm_next 指针。所以给定的代码给出了编译器错误。 那么如何遍历分配给一个粒子进程的所有 vm_area_struct 并实现上述目标呢?

我的代码:

static int __init dummy_init(void)
{
    printk("-----------------------------------------------------\n"); /*for aesthetics*/
    
    struct task_struct *task;
    struct mm_struct *mm;
    struct vm_area_struct *vma;
    unsigned long virt_size = 0;
    unsigned long phys_size = 0;

    if (target_pid < 0)
    {
        printk(KERN_ERR "Invalid input parameters.\n");
        return -EINVAL;
    }

    rcu_read_lock();

    task = pid_task(find_get_pid(target_pid), PIDTYPE_PID);
    if (!task)
    {
        printk(KERN_ERR "Process with PID %d not found.\n", target_pid);
        rcu_read_unlock();
        return -ESRCH;
    }

    mm = get_task_mm(task);
    if (!mm) {
        printk(KERN_ERR "Failed to get memory descriptor for PID %d.\n", target_pid);
        rcu_read_unlock();
        return -EFAULT;
    }


    down_read(&mm->mmap_lock);

    // Iterate through the VMAs and calculate sizes
    for (vma = mm->mmap_base; vma; vma = vma->vm_next) {
        virt_size += vma->vm_end - vma->vm_start;
    }

    up_read(&mm->mmap_lock);

    rcu_read_unlock();

    printk(KERN_INFO "PID: %d, Allocated Virtual Address Space: %lu KB\n", target_pid, virt_size >> 10);
    


    printk("-----------------------------------------------------\n"); /*for aesthetics*/

    return 0;
}
c linux-kernel kernel-module virtual-memory
1个回答
0
投票

显然,

vm_next
中由
vm_prev
vm_area_struct
形成的链表在6.1中被删除了,因为最近引入的枫树中已经存在相同的功能。 这是提交

现在走VMA似乎有两种主要方式:

  • 使用“枫树操作状态”(
    struct ma_state
    )通过
    mas_find()
    mas_for_each()
    等手动迭代枫树。
  • 使用
    struct vma_iterator
    和相关的辅助函数/宏:
    for_each_vma()
    vma_next()
    vma_prev()

这是一个例子:

struct vm_area_struct *vma;
VMA_ITERATOR(iter, mm, 0);

for_each_vma(iter, vma) {
    virt_size += vma->vm_end - vma->vm_start;
}
© www.soinside.com 2019 - 2024. All rights reserved.