您的位置:首页 > 运维架构 > Linux

Linux内核---62.用户空间获得变量的物理地址

2016-08-26 10:34 447 查看
1.  linux内核文档Documentation/vm/pagemap.txt

1.2  用户空间获取物理地址的代码

cong@msi:/work/test/ctest/vaddr$
cat test.c 

#include <stdio.h>

#include <unistd.h>

#include <inttypes.h>

#include <stdint.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#define page_map_file "/proc/self/pagemap"

#define PFN_MASK ((((uint64_t)1)<<55)-1)

#define PFN_PRESENT_FLAG (((uint64_t)1)<<63)

int mem_addr_vir2phy(unsigned long vir, unsigned long *phy)

{

    int fd;

    int page_size=getpagesize();

    unsigned long vir_page_idx = vir/page_size;

    unsigned long pfn_item_offset = vir_page_idx*sizeof(uint64_t);

    uint64_t pfn_item;

    fd = open(page_map_file, O_RDONLY);

    if (fd<0)

    {

        printf("open %s failed", page_map_file);

        return -1;

    }

    if ((off_t)-1 == lseek(fd, pfn_item_offset, SEEK_SET))

    {

        printf("lseek %s failed", page_map_file);

        return -1;

    }

    if (sizeof(uint64_t) != read(fd, &pfn_item, sizeof(uint64_t)))

    {

        printf("read %s failed", page_map_file);

        return -1;

    }

    if (0==(pfn_item & PFN_PRESENT_FLAG))

    {

        printf("page is not present");

        return -1;

    }

    *phy = (pfn_item & PFN_MASK)*page_size + vir % page_size;

    return 0;

}

void main()

{

    int a=0x12345678;

    unsigned long phy;

    mem_addr_vir2phy((unsigned long)&a, &phy);

    printf("vaddr=%p,phy=0x%lx\n", &a, phy);

    while(1)

    {

        sleep(100);

    }

}

注:函数mem_addr_vir2phy代码出自 

《Linux下获取虚拟地址对应的物理地址的方法》
http://www.lai18.com/content/7598292.html
这儿我只是打了一个main函数进行测试

二.验证结果的正确性

2.1 使用方法

cong@msi:/work/test/ctest/vaddr/Access_Physical_Memory$ sudo mknod /dev/dram c 85 0
cong@msi:/work/test/ctest/vaddr/Access_Physical_Memory$ ./fileview /dev/dram

注:上述驱动与fileview出自

《Linux用户程序如何访问物理内存》 http://ilinuxkernel.com/?p=1248 2.2.2 我的ubuntun 的内核版本是 3.13.0-49-generic

作了少许改动

27d26

< #include <linux/mm.h>

47,49c46,47

<     unsigned long pages = get_num_physpages();    

<     //dram_size = (loff_t)num_physpages << PAGE_SHIFT;

<     dram_size = pages << PAGE_SHIFT;

---

>     

>     dram_size = (loff_t)num_physpages << PAGE_SHIFT;

77c75

< #if 1

---

> #if 0

2.3 验证一下结果

2.3.1 这个是用户空间打印出来的物理地址是0x41F47284



2.3.2 这是物理内存0x41F47284处的数据



完全吻合,说明成功

2.4 代码下载

包括fileview和驱动


Access_Physical_Memory.rar
(下载后改名为Access_Physical_Memory.tar.bz2)

这个代码出自http://cs.usfca.edu/~cruse/cs635/

附录: 内核文档Documentation/vm/pagemap.txt

pagemap, from the userspace perspective

---------------------------------------

pagemap is a new (as of 2.6.25) set of
interfaces in the kernel that allow

userspace programs to examine the page tables and related information by

reading files in /proc.

There are three components to pagemap:

 * /proc/pid/pagemap. This
file lets a userspace process find out which

   physical frame each virtual page is mapped to. It
contains one 64-bit

   value for each virtual page, containing the following data (from

   fs/proc/task_mmu.c, above
pagemap_read):

    * Bits 0-54 page frame number (PFN) if present

    * Bits 0-4 swap type if swapped

    * Bits 5-54 swap offset if swapped

    * Bits 55-60 page shift (page size = 1<<page
shift)

    * Bit 61 reserved for future use

    * Bit 62 page swapped

    * Bit 63 page present

   If the page is not present but in swap, then the
PFN contains an

   encoding of the swap file number and the page's offset into the

   swap. Unmapped pages return a null PFN. This allows determining

   precisely which pages are mapped (or in swap) and comparing
mapped

   pages between processes.

   Efficient users of this interface will use /proc/pid/maps to

   determine which areas of memory are actually mapped and llseek to

   skip over unmapped regions.

 * /proc/kpagecount. This
file contains a 64-bit count of the number of

   times each page is mapped, indexed by PFN.

 * /proc/kpageflags. This
file contains a 64-bit set of flags for each

   page, indexed by PFN.

   The flags are (from fs/proc/page.c, above
kpageflags_read):

     0. LOCKED

     1. ERROR

     2. REFERENCED

     3. UPTODATE

     4. DIRTY

     5. LRU

     6. ACTIVE

     7. SLAB

     8. WRITEBACK

     9. RECLAIM

    10. BUDDY

    11. MMAP

    12. ANON

    13. SWAPCACHE

    14. SWAPBACKED

    15. COMPOUND_HEAD

    16. COMPOUND_TAIL

    16. HUGE

    18. UNEVICTABLE

    19. HWPOISON

    20. NOPAGE

    21. KSM

Short descriptions to the page flags:

 0. LOCKED

    page is being locked for exclusive access, eg. by
undergoing read/write IO

 7. SLAB

    page is managed by the SLAB/SLOB/SLUB/SLQB
kernel memory allocator

    When compound page is used, SLUB/SLQB will only set this
flag on the head

    page; SLOB will not flag it at all.

10. BUDDY

    a free memory block managed by the buddy system allocator

    The buddy system organizes free memory in blocks of various orders.

    An order N block has 2^N physically contiguous pages, with the BUDDY flag

    set for and _only_ for the
first page.

15. COMPOUND_HEAD

16. COMPOUND_TAIL

    A compound page with order N consists of 2^N physically contiguous pages.

    A compound page with order 2 takes the form of "HTTT", where H donates
its

    head page and T donates its tail page(s). The
major consumers of compound

    pages are hugeTLB pages (Documentation/vm/hugetlbpage.txt), the
SLUB etc.

    memory allocators and various device drivers. However in this interface,

    only huge/giga pages are made visible to end users.

17. HUGE

    this is an integral part of a HugeTLB page

19. HWPOISON

    hardware detected memory corruption on this page: don't touch the 

20. NOPAGE

    no page frame exists at the requested address

21. KSM

    identical memory pages dynamically shared between one or more processes

    [IO related page flags]

 1. ERROR IO error occurred

 3. UPTODATE page has up-to-date data

              ie. for file backed page: (in-memory
data revision >= on-disk
one)

 4. DIRTY page has been written to, hence contains new data

              ie. for file backed page: (in-memory
data revision > on-disk one)

 8. WRITEBACK page is being synced to disk

    [LRU related page flags]

 5. LRU page is in one of the LRU lists

 6. ACTIVE page is in the active LRU list

18. UNEVICTABLE page is in the unevictable (non-)LRU
list

                It is somehow pinned and not a candidate for LRU
page reclaims,

        eg. ramfs pages, shmctl(SHM_LOCK) and mlock() memory
segments

 2. REFERENCED page has been referenced since last LRU list enqueue/requeue

 9. RECLAIM page will be reclaimed soon after its pageout IO completed

11. MMAP a memory mapped page

12. ANON a memory mapped page that is not part of a file

13. SWAPCACHE page is mapped to swap space, ie. has
an associated swap entry

14. SWAPBACKED page is backed by swap/RAM

The page-types tool in this directory can be used to query the above flags.

Using pagemap to do something useful:

The general procedure for using pagemap to find out about a process' memory

usage goes like this:

 1. Read /proc/pid/maps to determine
which parts of the memory space are

    mapped to what.

 2. Select the maps you are interested in -- all
of them, or a particular

    library, or the stack or the heap, etc.

 3. Open /proc/pid/pagemap and seek to the
pages you would like to examine.

 4. Read a u64 for each page from pagemap.

 5. Open /proc/kpagecount and/or /proc/kpageflags. For each PFN
you just

    read, seek to that entry in the file, and read
the data you want.

For example, to find the "unique
set size" (USS), which is the
amount of

memory that a process is using that is not shared with any other process,

you can go through every map in the process, find the PFNs, look those
up

in kpagecount, and tally up the number of pages that are only referenced

once.

Other notes:

Reading from any of the files will return -EINVAL if you are not starting

the read on an 8-byte boundary (e.g., if you
seeked an odd number of bytes

into the file), or if the
size of the read is not a multiple of 8 bytes.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: