【摘要】Linux中的内核空间到用户空间的地址映射让用户层应用可以直接访问内核地址,这就是mmap方法。应用程序通过内存映射可以直接访问设备的I/O存储区或DMA缓冲。内存映射使用户空间的一段地址关联到设备内存上,程序在映射的地址范围内进行读取或者写入,实际上就是对设备的访问。
struct file_operations simple_fops = {
.owner = THIS_MODULE,
.open = simple_open,
.mmap = simple_mmap,// mmap接口
.release = simple_release,
};
在初始化的时候分配内存:
buffer = kmalloc(4096,GFP_KERNEL);
printk(" mmap buffer = %p\n",buffer);
buffer_area=(int *)(((unsigned long)buffer + PAGE_SIZE -1) & PAGE_MASK);
for (virt_addr=(unsigned long)buffer_area; virt_addr<(unsigned long)buffer_area+4096;
virt_addr+=PAGE_SIZE)
{
SetPageReserved(virt_to_page(virt_addr)); /*将页配置为保留*/
}
memset(buffer,‘C‘,100);// 初始化为‘C‘
simple_mmap函数实现mmap文件接口:
static int simple_mmap(struct file *filp, struct vm_area_struct *vma)
{
int ret;
ret = remap_pfn_range(vma,
vma->vm_start,
virt_to_phys((void*)((unsigned long)kmalloc_area)) >> PAGE_SHIFT,
vma->vm_end-vma->vm_start,
PAGE_SHARED);
if(ret != 0) {
return -EAGAIN;
}
return 0;
}
测试程序参考代码如下:
int main(void)
{
int fd;
char *addr=NULL;
fd = open("/dev/mmap",O_RDWR);
if(fd < 0) {
perror("open");
exit(1);
}
addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, 0);
if(addr == MAP_FAILED) {
perror("mmap");
exit(1);
}
printf("%s\n", addr);
memset(addr,‘f‘,100);
addr[0]=‘p‘;
printf("%s\n", addr);
munmap(addr,4096);
addr=NULL;
close(fd);
fd = open("/dev/mmap",O_RDWR);//重新打开进行验证
if(fd < 0) {
perror("open");
exit(1);
}
addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, 0);
if(addr == MAP_FAILED) {
perror("mmap");
exit(1);
}
printf("%s\n", addr);
munmap(addr,4096);
close(fd);
return(0);
}
运行结果如下:
[root@/home]#insmod demo.ko
mmap buffer = c3c82000
[root@/home]#mknod /dev/mmap c 224 0
[root@/home]#./read
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
pfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
pfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/xy010902100449/article/details/47029075