标题:
学习笔记-Linux 内存映射应用
[打印本页]
作者:
51hei小林
时间:
2016-9-24 22:33
标题:
学习笔记-Linux 内存映射应用
在实际应用过程中,为了更加高效率的让用户层与底层进行大量数据交换,可以采用内存映射的方式,将物理内存映射到进程空间内,应用程序可以直接对那块内存进行操作从而提高效率。
贴出经过验证的代码,共后续分析原理使用。
驱动程序
:
/*
* Copyright (c) 2016, Lovemengx
* All rights reserved.
*
* 文件名称: zhc_led.c
* 摘 要: mmap 学习驱动
*
* 当前版本: 1.0
* 作 者: Love 梦想
* 完成日期:
*
* 取代版本:
* 原作者 :
* 完成日期:
*/
#define __ISDEBUG__ // 开启打印信息
#include <mach/zhc_public.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#define DEVICE_NAME "mymap"
#define MALLOC_SIZE (8192 * 100)
#define USE_KMALLOC 1
static unsigned char array[10]= {0,1,2,3,4,5,6,7,8,9};
unsigned char *g_mmap_buff = NULL;
int g_mmap_buff_size = MALLOC_SIZE;
// 分配内存
int mmap_alloc(unsigned char **mmap_buff, int require_buf_size)
{
struct page *page;
unsigned char *mmap_buf_t;
int mmap_size;
int i;
mmap_size = PAGE_ALIGN(require_buf_size);
#if USE_KMALLOC //for kmalloc
mmap_buf_t = kzalloc(mmap_size, GFP_KERNEL);
if (!mmap_buf_t)
{
return -1;
}
for (page = virt_to_page(mmap_buf_t ); page < virt_to_page(mmap_buf_t + mmap_size); page++)
{
SetPageReserved(page);
}
#else //for vmalloc
mmap_buf_t = vmalloc(mmap_size);
if (!mmap_buf_t )
{
return -1;
}
for (i = 0; i < mmap_size; i += PAGE_SIZE)
{
SetPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf_t) + i)));
}
#endif
*mmap_buff = mmap_buf_t;
return mmap_size;
}
void mmap_free(unsigned char *mmap_buf, int mmap_size)
{
#if USE_KMALLOC
struct page *page;
for (page = virt_to_page(mmap_buf); page < virt_to_page(mmap_buf + mmap_size); page++)
{
ClearPageReserved(page);
}
kfree(mmap_buf);
#else
int i;
for (i = 0; i < mmap_size; i += PAGE_SIZE)
{
ClearPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf) + i)));
}
vfree(mmap_buf);
#endif
mmap_buf = NULL;
}
static int my_open(struct inode *inode, struct file *file)
{
dprintk();
return 0;
}
static int my_map(struct file *filp, struct vm_area_struct *vma)
{
int ret;
unsigned long pfn;
unsigned long start = vma->vm_start;
unsigned long size = PAGE_ALIGN(vma->vm_end - vma->vm_start);
int i;
unsigned char *mmap_buff = g_mmap_buff;
if (size > g_mmap_buff_size || !g_mmap_buff)
{
return -EINVAL;
}
dprintk("g_mmap_buff = 0x%x", g_mmap_buff);
//往该内存写10字节数据
for(i=0; i<10; i++)
{
mmap_buff[i] = array[i];
}
#if USE_KMALLOC
return remap_pfn_range(vma, start, (virt_to_phys(g_mmap_buff) >> PAGE_SHIFT), size, PAGE_SHARED);
#else
/* loop over all pages, map it page individually */
while (size > 0)
{
pfn = vmalloc_to_pfn(mmap_buff);
if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) < 0)
{
return ret;
}
start += PAGE_SIZE;
mmap_buff += PAGE_SIZE;
size -= PAGE_SIZE;
}
#endif
return 0;
}
static struct file_operations dev_fops =
{
.owner = THIS_MODULE,
.open = my_open,
.mmap = my_map,
};
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static ssize_t hwrng_attr_current_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int i;
for(i = 0; i < 10 ; i++)
{
printk("%d\n",g_mmap_buff[i]);
}
return 0;
}
static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
hwrng_attr_current_show,
NULL);
static int __init dev_init(void)
{
int ret;
dprintk();
//注册混杂设备
ret = misc_register(&misc);
//内存分配
ret = mmap_alloc(&g_mmap_buff, g_mmap_buff_size);
dprintk("ret = %d\n", ret);
if(NULL == g_mmap_buff)
{
eprintk("g_mmap_buff => NULL");
return 0;
}
ret = device_create_file(misc.this_device,&dev_attr_rng_current);
return ret;
}
static void __exit dev_exit(void)
{
dprintk();
//注销设备
misc_deregister(&misc);
mmap_free(g_mmap_buff, g_mmap_buff_size);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
应用:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#define PAGE_SIZE 4096 * 2
int main(int argc , char *argv[])
{
int fd;
int i;
unsigned char *p_map;
//打开设备
fd = open("/dev/mymap",O_RDWR);
if(fd < 0)
{
printf("open fail\n");
exit(1);
}
//内存映射
p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
if(p_map == MAP_FAILED)
{
printf("mmap fail\n");
goto here;
}
//打印映射后的内存中的前10个字节内容
for(i=0; i<10; i++)
{
printf("%d\n",p_map[i]);
p_map[i] = i + 1;
}
strcpy(p_map, "adcdefghij");
here:
munmap(p_map, PAGE_SIZE);
return 0;
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1