Chinaunix首页 | 论坛 | 博客
  • 博客访问: 75895
  • 博文数量: 13
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 164
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-06 22:57
文章存档

2013年(13)

我的朋友

分类: LINUX

2013-08-20 22:09:47

   最近有同事在读<>一文,我也看了下,写得不错,满通俗易懂的,但是其中关于

进程mem map 显示的东西,好象没提供,我搜了下只找到个显示全部mem map 的,于是自己写了一个,

虽然代码很小,但写+调试也花了半天时间,废话少说 ,具体代码如下:

   mem_map.c :

  1. #include <linux/kernel_stat.h>
  2. #include <linux/mm.h>
  3. #include <linux/hugetlb.h>
  4. #include <linux/mman.h>
  5. #include <linux/swap.h>
  6. #include <linux/highmem.h>
  7. #include <linux/pagemap.h>
  8. #include <linux/rmap.h>
  9. #include <linux/module.h>
  10. #include <linux/delayacct.h>
  11. #include <linux/init.h>
  12. #include <linux/writeback.h>
  13. #include <linux/memcontrol.h>
  14. #include <linux/mmu_notifier.h>
  15. #include <linux/kallsyms.h>
  16. #include <linux/swapops.h>
  17. #include <linux/elf.h>

  18. #include <asm/pgalloc.h>
  19. #include <asm/uaccess.h>
  20. #include <asm/tlb.h>
  21. #include <asm/tlbflush.h>
  22. #include <asm/pgtable.h>

  23. #define liuprintk printk

  24. unsigned short *proc_memmap;
  25. int msize;

  26. struct page *vm_get_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
  27. {
  28.     unsigned long pfn = pte_pfn(pte);


  29.     if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
  30.         liuprintk("\nliutest: has pure pfn \n");
  31.         #if 0
  32.         if (vma->vm_flags & VM_MIXEDMAP) {
  33.             if (!pfn_valid(pfn))
  34.                 return NULL; /* invalid page */
  35.             goto out;
  36.         } else {
  37.             unsigned long off;
  38.             off = (addr - vma->vm_start) >> PAGE_SHIFT; /* VM_PFNMAP 的处理*/
  39.             if (pfn == vma->vm_pgoff + off)
  40.                 return NULL;
  41.             if (!is_cow_mapping(vma->vm_flags))
  42.                 return NULL;
  43.         }
  44.         #endif
  45.     }
  46.     

  47. //out:
  48.     return pfn_to_page(pfn);
  49. }


  50. static inline void
  51. show_one_pte(struct mm_struct *mm, pte_t *src_pte, struct vm_area_struct *vma,
  52.         unsigned long addr) /* liunote linux pte */
  53. {
  54.     unsigned long vm_flags = vma->vm_flags;
  55.     pte_t pte = *src_pte; /* get pte val */
  56.     struct page *page;
  57.     int pm_index;

  58.     if (unlikely(!pte_present(pte))) {
  59.         
  60.         if (!pte_file(pte)) { /* liunote anymous page */
  61.             /* liunote can do it best */
  62.         }
  63.         goto out_show_pte;
  64.     }

  65.     page = vm_get_page(vma, addr, pte); /* 是normal page */
  66.     if (page) {
  67.               /* liunote get share proc num */
  68.         pm_index = (addr - vma->vm_start) /PAGE_SIZE;
  69.         proc_memmap[pm_index] = atomic_read(&(page)->_mapcount);
  70.         //printk("liutest pmd_index=0x%X,addr= 0x%X,vmstart=0x%X:,mapcount=%d", pm_index ,addr , vma->vm_start,atomic_read(&(page)->_mapcount));
  71.         if (proc_memmap[pm_index]==0){
  72.             proc_memmap[pm_index] =1;
  73.             }

  74.     }

  75. out_show_pte:
  76.     return;
  77. }

  78. static int show_ptes(struct mm_struct *mm, pmd_t *pmd, struct vm_area_struct *vma,
  79.         unsigned long addr, unsigned long end)
  80. {
  81.     pte_t *pte;
  82.     spinlock_t *ptl;

  83.     /* liunote below dst_pte is linux pte ??? */
  84.     pte = pte_offset_map_nested(pmd, addr);
  85.     ptl = pte_lockptr(mm, pmd);

  86.     /* liunote need lock to read it ??? */
  87.     /* spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);*/
  88.     

  89.     do {
  90.         if (pte_none(*pte)) { /* src_pte = 0 */
  91.          //liuprintk("\nliutest: bad pte=0x%X,addr=0x%X\n",pte,addr);
  92.             continue;
  93.         }
  94.         show_one_pte(mm, pte, vma, addr);

  95.     } while (pte++, addr += PAGE_SIZE, addr != end);

  96.     /* spin_unlock(ptl); */

  97.     return 0;
  98. }

  99. static inline int show_pmds(struct mm_struct *mm, pud_t *pud, struct vm_area_struct *vma,
  100.         unsigned long addr, unsigned long end)
  101. {
  102.     pmd_t * pmd;
  103.     unsigned long next;

  104.     pmd = pmd_offset(pud, addr);
  105.     do {
  106.         next = pmd_addr_end(addr, end);
  107.         if (pmd_none_or_clear_bad(pmd)){
  108.             liuprintk("\nliutest: bad pmd=0x%X,addr=0x%X\n",pmd,addr);
  109.             continue;
  110.         }
  111.         if (show_ptes(mm, pmd,
  112.                         vma, addr, next))
  113.             return -ENOMEM;
  114.     } while (pmd++, addr = next, addr != end);
  115.     return 0;
  116. }

  117. static inline int show_puds(struct mm_struct *mm, pgd_t *pgd, struct vm_area_struct *vma,
  118.         unsigned long addr, unsigned long end)
  119. {
  120.     pud_t *pud ;
  121.     unsigned long next;

  122.     pud = pud_offset(pgd, addr);
  123.     do {
  124.         next = pud_addr_end(addr, end);
  125.         if (pud_none_or_clear_bad(pud)){
  126.             liuprintk("\n liutest: bad pud=0x%X,addr=0x%X\n",pud,addr);
  127.             continue;
  128.         }
  129.         if (show_pmds(mm, pud,
  130.                         vma, addr, next))
  131.             return -ENOMEM;
  132.     } while (pud++, addr = next, addr != end);
  133.     return 0;
  134. }


  135. // liuadd for print pte
  136. int show_pages(struct mm_struct * mm, struct vm_area_struct *vma)
  137. {
  138.     pgd_t *pgd;
  139.     unsigned long next;
  140.     unsigned long addr = vma->vm_start;
  141.     unsigned long end = vma->vm_end;
  142.     int ret,i;
  143.     int pages =0;

  144.        // according vm size ,malloc proc memmap
  145.        msize = end-addr;
  146.        msize = (msize & (PAGE_SIZE-1)) ? (msize+PAGE_SIZE)/PAGE_SIZE : msize/PAGE_SIZE;
  147.         
  148.        liuprintk("\nliutest: msize =0x%X, PAGE_SIZE=0x%X\n",msize,PAGE_SIZE);
  149.     
  150.        proc_memmap = kmalloc( msize*(sizeof(unsigned short)),GFP_KERNEL);
  151.     if(proc_memmap == NULL){
  152.         printk("\n liutest : proc mem map alloc fail \n");
  153.         return 1;
  154.     }
  155.     for(i=0; i<msize;i++)
  156.         proc_memmap[i] = 0;

  157.     /*
  158.     if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP|VM_INSERTPAGE))) {
  159.         if (!vma->anon_vma)
  160.             return 0;
  161.     }
  162.     */

  163.     ret = 0;
  164.     pgd = pgd_offset(mm, addr);
  165.     do {
  166.         next = pgd_addr_end(addr, end);
  167.         if (pgd_none_or_clear_bad(pgd)){
  168.             liuprintk("\nliutest: bad pgd=0x%X,addr=0x%X\n",pgd,addr);
  169.             continue;
  170.         }
  171.         if (unlikely(show_puds(mm, pgd, vma, addr, next))) {
  172.             ret = -ENOMEM;
  173.             break;
  174.         }
  175.     } while (pgd++, addr = next, addr != end);

  176. #if 1
  177.     for(i=0; i<msize;i++)
  178.         if(proc_memmap[i])
  179.            pages++;

  180.     printk("\nliutest: this vm area has pages =0x%X\n",pages);    
  181.     

  182.     // free memmap
  183.     kfree(proc_memmap);
  184. #endif    

  185.     return ret;
  186. }

  187. #undef liuprintk

上面mem_map.c 文件加到proc 目录下

然后在task_mmu.c show_map_vma 函数末尾加上:

show_pages(vma->vm_mm, vma);

proc 下面Makefile 加上 mem_map.o

代码有点乱,不过测试过还行,内容全在proc_memmap 数组里,大小为msize,

可根据自己喜好显示从proc 输出

下面是测试busybox 内存情况

 

Cd proc

Cd 1

Cat maps 显示如下:

 

00008000-00100000 r-xp 00000000 00:01 60         /bin/busybox

 Pages:0xF8-0x4D       ( F8 , 实际占用4D ,下面是实际页内存引用情况)

0x0002 0x0002 0x0000 0x0000 0x0002 0x0002 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000

0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0000 0x0001 0x0001 0x0000 0x0000 0x0000

0x0000 0x0000 0x0000 0x0000 0x0002 0x0000 0x0002 0x0000 0x0000 0x0002 0x0002 0x0002 0x0002 0x0000 0x0000 0x0000 0x0000 0x0001 0x0001 0x0001 0x0001 0x0000 0x0000 0x0000 0x0001 0x0001 0x0000 0x0000 0x0001 0x0001 0x0001 0x0001

0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0001 0x0002 0x0002 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0002 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000

0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0002 0x0000 0x0000 0x0002 0x0002 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0002 0x0002

0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0002 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0000 0x0000 0x0000 0x0002 0x0000 0x0000 0x0000 0x0000 0x0000

0x0000 0x0002 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0002 0x0001 0x0002 0x0000 0x0002 0x0000 0x0001 0x0001 0x0000 0x0000 0x0000

0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0000 0x0000 0x0002 0x0002 0x0000 0x0002 0x0002 0x0000 0x0000 0x0002 0x0000 0x0001 0x0001 0x0001 0x0001 0x0000 0x0000

 

00107000-00108000 rw-p 000f7000 00:01 60         /bin/busybox

 Pages:0x1-0x1

0x0001

00108000-0012e000 rw-p 00108000 00:00 0          [heap]

 Pages:0x26-0x6

0x0001 0x0001 0x0000 0x0001 0x0001 0x0001 0x0001 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000

0x0000 0x0000 0x0000 0x0000 0x0000 0x0000

40000000-40001000 rw-p 40000000 00:00 0

 Pages:0x1-0x1

0x0001

be844000-be859000 rw-p befeb000 00:00 0          [stack]

 Pages:0x15-0x2     (这是栈,有15 , 实际占用2 ,下面也可以看出,占了倒数的两页符合栈特性,)

0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0001 0x0001

 

 

 

 

阅读(1601) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~