免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1569 | 回复: 0
打印 上一主题 下一主题

[原创]写了一个查看进程线性地址与物理地址对应关系的代码 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-05-09 00:24 |只看该作者 |倒序浏览

                ------------------------------------------
转载请注明出处:http://lullaby2005.cublog.cn/
------------------------------------------
代码如下:
               
                #include linux/module.h>
#include linux/init.h>
#include linux/kernel.h>
#include linux/moduleparam.h>
#include linux/mm.h>
#include linux/sched.h>
#include linux/string.h>
#include linux/fs.h>
#include asm/pgtable.h>
#include asm/unistd.h>
#include asm/uaccess.h>
#define PGD_PUD_PMD_NONE -3
#define NOT_MAPPED  -2
#define NOT_IN_RAM -1
#define FILE_NAME_LEN 50
#define BUF_LEN 100
static  int pid_from_user = 0;
static char *log_file = "/home/my_kernel_log_test";
static int get_walk_page_status = 0;
static struct file *log_file_struct = NULL;
static mm_segment_t old_fs;
unsigned long my_find_phyaddr(struct mm_struct *my_mm, unsigned long my_va, int *status);
static int log_to_file(struct file *my_file, char *buf, unsigned int buf_len);
module_param(pid_from_user, int, 0);
module_param(log_file, charp, 0);
static int __init test_init()
{
        printk("Hello world!\n");
        int status = 0;
        unsigned int i = 0;
        struct mm_struct *my_mm = NULL;
        struct vm_area_struct *my_vm_area = NULL, *tmp = NULL;
        unsigned long my_start, my_end, my_phy_addr;
        char my_buf[BUF_LEN];
        log_file_struct = filp_open(log_file, O_RDWR | O_APPEND | O_CREAT, 0644);
  if (IS_ERR(log_file_struct))
  {
          printk("error occured while opening file %s\n", log_file);
          return 0;
  }
  old_fs = get_fs();
  set_fs(KERNEL_DS);
  
        struct task_struct *tsk = find_task_by_pid(pid_from_user);
        if (NULL == tsk)
        {
                printk("find pid %d failed!\n", pid_from_user);
                return 0;
        }
        my_mm = tsk->mm;
        if (NULL == my_mm)
        {
                printk("the task %d is a kernel thread, goodbye!\n", pid_from_user);
                return 0;
        }
      
        my_vm_area = my_mm->mmap;
        if (NULL == my_vm_area)
        {
                printk("there's no linear area in the task %d, goodbye!\n", pid_from_user);
                return 0;
        }
#if 0
        printk("Basic information:");
        printk("total_vm = 0x%x, locked_vm = 0x%x, shared_vm = 0x%x, exec_vm = 0x%x\n", my_mm->total_vm, my_mm->locked_vm, my_mm->shared_vm, my_mm->exec_vm);
        printk("stack_vm = 0x%x, reserved_vm = 0x%x, def_flags = 0x%x, nr_ptes = 0x%x\n", my_mm->stack_vm, my_mm->reserved_vm, my_mm->def_flags, my_mm->nr_ptes);
        printk("start_code = 0x%x, end_code = 0x%x, start_data = 0x%x, end_data = 0x%x\n", my_mm->start_code, my_mm->end_code, my_mm->start_data, my_mm->end_data);
        printk("start_brk = 0x%x, brk = 0x%x, start_stack = 0x%x\n", my_mm->start_brk, my_mm->brk, my_mm->start_stack);
        printk("arg_start = 0x%x, arg_end = 0x%x, env_start = 0x%x, env_end = 0x%p\n", my_mm->arg_start, my_mm->arg_end, my_mm->env_start, my_mm->env_end);
#else
        memset(my_buf, 0, sizeof(my_buf));
        sprintf(my_buf, "Basic information:\n");
        log_to_file(log_file_struct, my_buf, BUF_LEN-1);
      
        sprintf(my_buf, "total_vm = 0x%x, locked_vm = 0x%x, shared_vm = 0x%x, exec_vm = 0x%x\n", my_mm->total_vm, my_mm->locked_vm, my_mm->shared_vm, my_mm->exec_vm);
        log_to_file(log_file_struct, my_buf, BUF_LEN-1);
      
        sprintf(my_buf, "stack_vm = 0x%x, reserved_vm = 0x%x, def_flags = 0x%x, nr_ptes = 0x%x\n", my_mm->stack_vm, my_mm->reserved_vm, my_mm->def_flags, my_mm->nr_ptes);
        log_to_file(log_file_struct, my_buf, BUF_LEN-1);
#endif
        tmp = my_vm_area;
        while (tmp != NULL)
        {
//                printk("%d: vm_start = 0x%x, vm_end = 0x%x\n", ++i, tmp->vm_start, tmp->vm_end);
                my_start = tmp->vm_start;
                my_end = tmp->vm_end;
          while (my_end >= my_start)
          {
                  my_phy_addr = my_find_phyaddr(my_mm, my_start, &status);
                 
                  if (PGD_PUD_PMD_NONE == status)
                  {
                                sprintf(my_buf, "%lx --> something is wrong\n", my_start);
                                log_to_file(log_file_struct, my_buf, BUF_LEN-1);
                          //        printk("%lx --> something is wrong\n", my_start);
                  }
                  else if (NOT_MAPPED == status)
                  {                        
                                sprintf(my_buf, "%lx --> not mapped to physical frame yet\n", my_start);
                                log_to_file(log_file_struct, my_buf, BUF_LEN-1);
                          //        printk("%lx --> not mapped to physical frame yes\n", my_start);
                  }
                  else if (NOT_IN_RAM == status)
                  {      
                                sprintf(my_buf, "%lx --> not in ram now\n", my_start);
                                log_to_file(log_file_struct, my_buf, BUF_LEN-1);
                          //        printk("%lx --> not in ram now\n", my_start);
                  }
                  else
                  {
                                sprintf(my_buf, "%lx  %lx\n", my_start, my_phy_addr);
                                log_to_file(log_file_struct, my_buf, BUF_LEN-1);
                                 //printk("%lx  %lx\n", my_start, my_phy_addr);
                  }
                  my_start += PAGE_SIZE;
          }      
                tmp = tmp->vm_next;
        }
      
        return 0;
}
static void __exit test_exit()
{
        set_fs(old_fs);
        if (NULL != log_file_struct)
                filp_close(log_file_struct, NULL);
               
        printk("Goodbye the world!\n");
        return;
}
unsigned long my_find_phyaddr(struct mm_struct *my_mm, unsigned long my_va, int *status)
{
        pgd_t *pgd = NULL;
        pud_t *pud = NULL;
        pmd_t *pmd = NULL;
        pte_t *pte = NULL;
      
        pgd = pgd_offset(my_mm, my_va); /*get the pdg entry pointer*/
        if (pgd_none(*pgd))
        {
                printk("this is impossible on ia32, maybe something is wrong, maybe I'm wrong..., line %d\n", __LINE__);
                *status = PGD_PUD_PMD_NONE;
                return 0;
        }
      
        pud = pud_offset(pgd, my_va);
        if (pud_none(*pud))
        {
                printk("this is impossible on ia32, maybe something is wrong, maybe I'm wrong..., line %d\n", __LINE__);
                *status = PGD_PUD_PMD_NONE;
                return 0;
        }
      
        pmd = pmd_offset(pud, my_va);
        if (pmd_none(*pmd))
        {
                printk("this is impossible on ia32, maybe something is wrong, maybe I'm wrong..., line %d\n", __LINE__);
                *status = PGD_PUD_PMD_NONE;
                return 0;
        }
      
        pte = pte_offset_kernel(pmd, my_va);
        if (pte_none(*pte))
        {
                *status = NOT_MAPPED;
                return 0;
        }
        if (!pte_present(*pte))
        {
                *status = NOT_IN_RAM;
                return 0;
        }
        *status = 0;      
        return pte_val(*pte);
}               
static int log_to_file(struct file *my_file, char *buf, unsigned int buf_len)
{
  my_file->f_op->write(my_file, buf, strlen(buf),&my_file->f_pos);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lullaby2005@gmail.com");
用法如下:
insmod xxx.ko pid_from_user=your_process_pid log_file="you_file_path"
传入的pid_from_user是你的用户进程的pid,log_file是用来记录线性地址对应的物理地址的信息。
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/38534/showart_1922720.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP