前些日子看到linuxforum上wheelz发的一个帖子, kernel空间和用户空间通信的经典的例子 。
特整理一下:
kernel代码:
#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)); //#define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT)) //12 printk("<1> p = 0x%08x/n", p); //在共享内存中写上一个字符串 strcpy(p, "Hello world!/n"); return 0; }
static void __exit exit(void) { ClearPageReserved(virt_to_page(p)); free_pages(p, 0); }
module_init(init); module_exit(exit);
|
用户空间的测试程序:
#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 0xcf9e5000 //这里是硬编址的, 可以通过ioctl 或者proc来实现的。
int main() { 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; }
|
确实是个好例子。