栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

mmap实验例子

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

mmap实验例子

mmap内存映射实现

实验内容:在内核下面申请4K大小的内存(kmalloc申请的物理连续内存),在应用程序中通过mmap把内核态下申请的内存块映射到用户空间,然后在应用程序中通过read,write操作读写内核空间数据,最后读取用户态映射的地址空间,看内容是否和内核数据空间一致。

我的编译工具:
/opt/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gun/bin/arrch64-linux-gun-gcc

内核实现:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


static struct proc_dir_entry *mmap_dir  = NULL;
static struct proc_dir_entry *mmap_file = NULL;

struct self_data {
    int arry[1024];
};

int    alloc_size = 0;
struct self_data *p_mem = NULL;



static int mmap_open(struct inode *p_node, struct file *p_file);
static ssize_t mmap_read(struct file *p_file, char __user *p_buf, size_t size, loff_t * p_loff);
static ssize_t mmap_write(struct file *p_file, const char __user *p_buf, size_t size, loff_t *p_loff);
static int mmap_mmap(struct file *p_file, struct vm_area_struct *vma);
static int mmap_release(struct inode *p_node, struct file *p_file);

static const struct file_operations mmap_opts = {
    .owner   = THIS_MODULE,
    .open    = mmap_open,
    .read    = mmap_read,
    .write   = mmap_write,
    .mmap    = mmap_mmap,
    .release = mmap_release,

};

int mmap_release(struct inode *p_node, struct file *p_file)
{
    return 0;
}

static int mmap_open(struct inode *p_node, struct file *p_file)
{
    return simple_open(p_node, p_file);
}

static ssize_t mmap_read(struct file *p_file, char __user *p_buf, size_t size, loff_t * p_loff)
{
    copy_to_user(p_buf, p_mem, size);

    return size;

}

static ssize_t mmap_write(struct file *p_file, const char __user *p_buf, size_t size, loff_t *p_loff)
{
    copy_from_user(p_mem, p_buf, size);

    return size;
}
static int mmap_mmap(struct file *p_file, struct vm_area_struct *vma)
{
    unsigned long phyaddr = 0;
    unsigned long size = vma->vm_end - vma->vm_start;
    int ret;

    if (p_mem) {
        phyaddr = __pa(p_mem);
    }
    if (phyaddr  == 0) {
        pr_err("get phy addr failed!n");
    }
    ret = remap_pfn_range(vma, vma->vm_start, phyaddr >> PAGE_SHIFT, size, PAGE_SHARED);
    if (ret != 0) {
        pr_err("remap_pfn_range failed!n");
    }
    printk(KERN_EMERG"phyaddr = %p, remap size = %dn", phyaddr, size);

    return ret;
}

static int __init my_mmap_init(void)
{
    mmap_dir= proc_mkdir("module_mmap", NULL);
    if (mmap_dir == NULL) {
    	pr_err("proc_mkdie failed!n");
    }

   mmap_file =  proc_create("self_mmap", 0666, mmap_dir, &mmap_opts);
   if (mmap_file == NULL) {
       pr_err("proc_data failed!n");
   }

    alloc_size = PAGE_ALIGN(sizeof(struct self_data));
    p_mem  = kmalloc(alloc_size, GFP_KERNEL);
    if (p_mem == NULL) {
        pr_err("kmalloc failed!n");
    }

    memset(p_mem, 0, alloc_size);
    
    printk(KERN_EMERG"alloc size = %dn", alloc_size);

    return 0;
}

static void __exit my_mmap_exit(void)
{
    if (p_mem) {
        kfree(p_mem);
    }
    if (mmap_dir) {
    
    }
}

module_init(my_mmap_init);
module_exit(my_mmap_exit);

MODULE_LICENSE("GPL v2");

Makefile 文件:

KERNDIR ?=
ARCH ?=
PWD := $(shell pwd)

CROSS_COMPILE ?=
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld

obj-m := module_mmap.o

all:
	 $(MAKE) ARCH=$(ARCH) -C $(KERNDIR)  M=${PWD} modules

用户态实现:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


char *p_file = NULL;
char buf[1024];

int main (void)
{
    int fd = 0;
    int i;
    void *p_viraddr = NULL;
    ssize_t len;

    for (i = 0; i < 1024; i++) {
        buf[i] = 'r';   
    }

    fd =  open("/proc/module_mmap/self_mmap", O_RDWR);
    if (fd < 0) {
        printf("file open failedn");
        return 0;
    }

    
    p_viraddr = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (p_viraddr == NULL) {
		printf("mmap failed!n");
		close(fd);
		return 0;
	}
	
	
    len = write(fd, buf, 1024);
    if (len < 0) {
        printf("write errorn");
		close(fd);
		return 0;
    }
   
   sleep(5);
   memset(buf, 0, 1024);

   len = read(fd, buf, 1024);
   if (len < 0) {
        printf("read errorn");
	    close(fd);
        return 0;
   }
   printf("kernal addr content: n");
   for (i = 0; i < 1024; i++) {
       printf("%c", buf[i]);
   }

   printf ("nuser addr content: n");
   for (i = 0; i < 1024; i++) {
       printf("%c",((char *)p_viraddr)[i]);
   }
   close(fd);

   return 0;
}

用户态文件编译:

/opt/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gun/bin/arrch64-linux-gun-gcc -g mmap_main.c -o mmap_main

最后:将编译出的module_mmap.ko 和mmap_main文件,拷贝到内核编译结果目录:rootf, 然后image打包。
实验现象:
kernal addr content:
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr …
user addr content:
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr…

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/460179.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号