This post will introduce a funny way to access physical memory from user space, I will:
- write a kernel module and load it. The module will allocate a page in kernel space and write some characters in this page.
- write a user program, read the content of that page and print.
What’s the difficulty in doing this ?
As we know, a user program (or process) has its own virtual address space, when it calls malloc() to apply a block of memory, the malloc will return the start address of the allocated virtual memory, user program doesn’t know the actual start address of physical memory.
Here, I will access the physicall address from a user program with the help of /dev/mem.
Firstly, let’s talk about /dev/mem, and enable access to /dev/mem
/dev/mem is a virtual device which provides a way to access to system physical memory, but unfortunately, in most Linux distributions, userspace(including root) can’t read /dev/mem by default . So, if you want to use this feature, please compile a new kernel by yourself. I will show you step by step.
go to www.kernel.org download a latest version of linux kernel.
the following is in command line ( shell ):
$ sudo su //change to root
# make menuconfig // this will generate a .config file
# vim .config
ok, continue to compile it.
# make -j4
# make modules
# make module_install
# make install
reboot my computer, and I will enter OS with a new kernel.
Secondly, let’s write a kernel module.
to compile the kernel module, I need a Makefile:
after make, a kernel module “mmap.ko” will appears in my current directory.
# insmod mmap.ko
then, look the “printk(“addr= 0x%08x\n”, (int)addr);” in `dmesg`
[80005.141345] addr= 0x77128000
Finally, write a user program using mmap() function.
the declaration of mmap is:
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
`man 2 mmap` says:
The contents of a file mapping are initialized using `length` bytes starting at offset `offset` in the file (or other object) referred to by the file descriptor fd. `offset` must be a multiple of the page size.
so, I can use the address printed by mmap.ko (0x77128000) as the `offset` parameter.
Attention, the KERNEL_PHY_ADDR may vary every time you load the mmap.ko, so, if you copy the code and complie it on your own computer, please remember to change it.
ok, compile user.c
# gcc -o user user.c
make sure you are a super user
the out put is:
With great power, comes great responsibility