例子中,用户态程序的KERNEL_VIRT_ADDR
就是内核模块打印的地址p,这里是hard coding(先加载内核模块,再把打印的地址赋值给KERNEL_VIRT_ADDR),可以采用其他的方式传递。
2.6内核验证。
内核模块=============================================================
#
include
<
linux/
config.
h>
#
include
<
linux/
module.
h>
#
include
<
linux/
kernel.
h>
#
include
<
linux/
mm.
h>
MODULE_LICENSE(
"GPL"
)
;
MODULE_AUTHOR(
"Wheelz"
)
;
MODULE_DESCRIPTION(
"mmap demo"
)
;
static
unsigned
long
p
=
0;
static
int
__init init(
void
)
{
//分配共享内存(一个页面)
p
=
__get_free_pages(
GFP_KERNEL,
0)
;
SetPageReserved(
virt_to_page(
p)
)
;
printk(
"<1> p = 0x%08x/n"
,
p)
;
//在共享内存中写上一个字符串
strcpy
(
p,
"Hello world!/n"
)
;
return
0;
}
static
void
__exit fini(
void
)
{
ClearPageReserved(
virt_to_page(
p)
)
;
free_pages(
p,
0)
;
}
module_init(
init)
;
module_exit(
fini)
;
Makefile文件=================================================================================
obj-m :=XXX.o
XXX-y:=YYYY.o
KBUILD_EXTRA_SYMBOLS+=/home/share/kernel/Module.symvers
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.ko
rm -rf *.mod.*
rm -rf *.o
rm -rf *.order
rm -rf Module.symvers
用户态程序========================================================================================================
#
include
<
sys/
mman.
h>
#
include
<
sys/
types.
h>
#
include
<
sys/
stat.
h>
#
include
<
fcntl.
h>
#
include
<
stdio.
h>
#
define
PAGE_SIZE
(
4*
1024)
#
define
PAGE_OFFSET 0xc0000000
#
define
KERNEL_VIRT_ADDR 0xc5e3c000
int
main(void
)
{
char
*
buf;
int
fd;
unsigned
long
phy_addr;
fd=
open
(
"/dev/mem"
,
O_RDWR)
;
if
(
fd
=
=
-
1)
perror
(
"open"
)
;
phy_addr=
KERNEL_VIRT_ADDR
-
PAGE_OFFSET;
buf=
mmap(
0,
PAGE_SIZE,
PROT_READ|
PROT_WRITE,
MAP_SHARED,
fd,
phy_addr)
;
if
(
buf
=
=
MAP_FAILED)
perror
(
"mmap"
)
;
puts
(
buf)
;
//打印共享内存的内容
munmap(
buf,
PAGE_SIZE)
;
close
(
fd)
;
return
0;
}