1. linux内核文档Documentation/vm/pagemap.txt
1.2 用户空间获取物理地址的代码
注:函数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
注:上述驱动与fileview出自
《Linux用户程序如何访问物理内存》
http://ilinuxkernel.com/?p=1248
2.2.2 我的ubuntun 的内核版本是 3.13.0-49-generic
作了少许改动
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
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);
- }
- }
《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.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.