Linux proc模块中的虚拟地址到物理地址转换

时间:2016-06-11 12:53:11

标签: c memory-management linux-kernel kernel-module

我试图创建自己的proc节点" os_pagemap"在Linux上(使用odroid)

该节点的目标是打印所有物理内存页面的信息。 (sudo cat / proc / os_pagemap)

像这样:

[PHY] Virt 483252 Phy 266908 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 483253 Phy 266909 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 483254 Phy 266910 VMA 0 PID 5773 PNAME com.sec.android.app.keyboard
[PHY] Virt 398391 Phy 266920 VMA /dev/ashmem/dalvik-bitmap-1 PID 5773 PNAME com.sec.android.app.keyboard

其中VMA是指VMA名称

为了实现目标,我的设计是这样的:

1. read_lock(&tasklock)
2. for_each_process(p) => get pids
3. read_unlock(&tasklock)
4. Loop for each pid
   1)task = get_pid_task(pid)
   2)if task==NULL => skip
   3)mm=task->mm
   4)down_read(&mm->mmap_sem)
   5)Loop for each vma in mm
        1>store vma information into os_pagemap_struct
   6)up_read(&mm->mmap_sem)
5. Print os_pagemap_struct

但是,我无法找到解决方法 "获取vma信息"和"打印os_pagemap_struct"

这是我已经完成的代码: 我只得到" vm_start"和" vm_end"而我打印得不好。

struct os_pagemap{
    unsigned long vm_start;
    unsigned long vm_end;
    //more on...
};

static ssize_t ospagemap_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    struct task_struct * p = NULL;
    char * pagemap_buf = kmalloc(500, GFP_KERNEL);
    int i = 0, j;
    int cur = 0, bytes=0;
    struct pid *pid_struct;
    int pid[100];
    struct mm_struct* mm;
    struct os_pagemap pagemap;
    struct vm_area_struct * vma;
    int count = 0;
    int buf_size = 0;

    read_lock(&tasklist_lock);

    for_each_process(p){ //get all process' pids
        pid[i] = p->pid;

        i++;
    }

    read_unlock(&tasklist_lock);

    for (j = 0; j < i; j++){ //loop for each process
        pid_struct = find_get_pid(pid[j]);
        p = get_pid_task(pid_struct, PIDTYPE_PID);
        put_pid(pid_struct);

        if (p == NULL){ //skip this task
            printk("[%d]p is NULL", pid[j]);
            continue;
        }

        mm = p->mm;
        if (mm == NULL){
            printk("\n[%d]mm is NULL!\n",pid[j]);
            continue;
        }


        down_read(&mm->mmap_sem);

        vma = mm->mmap;

        count = 0;
        while (1){ //loop for each vma
            if (vma == NULL){
                printk("\n[%d]vma is NULL!\n", pid[j]);
                break;
            }


            if (buf_size >= 450){
                printk("Realloc size : %d\n", cur + 500);
                krealloc(pagemap_buf, cur + 500, GFP_KERNEL);
                buf_size = 0;
            }


            pagemap.vm_start = vma->vm_start;
            pagemap.vm_end = vma->vm_end;


            bytes = snprintf((cur > 0) ? cur + pagemap_buf : pagemap_buf,
                500 - cur,
                "Task : [%d]%s start : %lu end : %lu\n", p->pid, p->comm,  
                  pagemap.vm_start, pagemap.vm_end);

            printk("Task : [%d]%s start : %lu end : %lu\n", p->pid, p->comm, 
                  pagemap.vm_start, pagemap.vm_end);

            cur += bytes;
            buf_size += bytes;

            vma = vma->vm_next;
            count++;
        }

        up_read(&mm->mmap_sem);
    }

    printk("cur : %d\n", cur);
    copy_to_user(buf, pagemap_buf, (size<cur) ? size : cur);

    return (size<cur) ? size : cur;
}

static int ospagemap_open(struct inode *inode, struct file *file)
{
    printk("ospagemap opened");
    return 0;
}
const struct file_operations proc_ospagemap_operations = {
    .llseek = mem_lseek, /* borrow this */
    .read = ospagemap_read,
    .open = ospagemap_open,
};
static int __init proc_ospagemap_init(void)
{
    proc_create("os_pagemap", 0, NULL, &proc_ospagemap_operations);
    return 0;
}

fs_initcall(proc_ospagemap_init);

0 个答案:

没有答案