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.
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.
相关文章推荐
- Linux 内核空间虚拟地址和物理地址相互转换
- linux 内存映射 remap_pfn_range操作(内核地址映射到用户空间)
- Linux下将物理地址映射到用户空间
- Unix v6中对虚拟地址映射到物理地址以及在内核态如何访问用户空间的u值
- 在 Linux 下用户空间与内核空间数据交换的方式: procfs、seq_file、debugfs和relayfs
- Linux 系统内核空间与用户空间通信的实现与分析
- 函数 ioremap 物理地址到内核映射空间的映射函数
- 在 Linux 下用户空间与内核空间数据交换的方式
- Linux 系统内核空间与用户空间通信的实现与分析
- 在 Linux 下用户空间与内核空间数据交换的方式,第 2 部分: procfs、seq_file、debugfs和relayfs
- linux用户空间和内核exit的语义--linux没有线程
- 在 Linux 下用户空间与内核空间数据交换的方式
- Linux 系统内核空间与用户空间通信的实现与分析
- 在 Linux 下用户空间与内核空间数据交换的方式,第 2 部分: procfs、seq_file、debugfs和relayfs
- Linux 系统内核空间与用户空间通信的实现与分析
- linux用户空间和内核空间之细说
- Linux 系统内核空间与用户空间通信的实现与分析
- linux内存布局的内核实现--用户空间的映射方式
- linux 内核与用户空间通信之netlink使用方法
- Linux 系统内核空间与用户空间通信的实现与分析 from [http://www-900.ibm.com/developerWorks/cn/linux/]