例子中,用户态程序的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; } |