linux mmap驱动内核共享内存模块以及用户态测试

//micros_mmap.c
#include 	<linux/kernel.h>
#include	<linux/module.h>
#include	<linux/init.h>
#include 	<linux/slab.h>        /* kmalloc() */
#include	<linux/fs.h>
#include	<linux/mm.h>
#include	<linux/cdev.h>
#include	<linux/errno.h>
#include	<linux/types.h>
#include	<linux/interrupt.h>
#include	<linux/delay.h>
#include    <linux/errno.h>
#include    <linux/sched.h>
#include    <linux/semaphore.h>
//#include    <linux/system.h>
#include	<linux/uaccess.h>
//#include	<asm/arch/irqs.h>
#include 	<linux/io.h>
#include 	<linux/version.h>
//#include    <asm/hardware.h>
#include    <linux/delay.h>

//#include    <asm/arch/sep4020_hal.h>

#define	DRIVE_MAJOR				165
#define	DRIVE_NAME				"Test drv"
typedef	struct
{
	dev_t			dev_num ;
	struct	cdev	cdev ;	
			
}code_dev ;

static code_dev	test_dev ;
unsigned char data_source;
unsigned char *testmap;
//unsigned char *kmalloc_area;
void *kmalloc_area;
unsigned long  msize;
static int	test_open(struct inode *inode , struct file *filp)
{
	printk("<MICROS_MMAP> : I come in test_open function. \n");
	return 0 ;
}
static int	test_close(struct inode *inode , struct file *filp)
{
	printk("<MICROS_MMAP> : I come in test_close function. \n");
	return 0 ;
}

static ssize_t test_write(struct file *filp, const char __user *buf,size_t count, loff_t *ppos)
{
    printk("<MICROS_MMAP> : I come in test_write function. \n");
    if(copy_from_user(&data_source,buf,sizeof(data_source)))
    {
        printk("write error!\n");
    }
	return(sizeof(data_source));
}

static ssize_t test_read(struct file *filp, char __user *buf,size_t count,loff_t *ppos)
{
	printk("<MICROS_MMAP> : I come in test_read function. \n");
	if(copy_to_user(buf,&data_source,sizeof(data_source)))
	{
		printk("read error!\n");
	} 
	return(sizeof(data_source));
}
static int test_mmap(struct file *file,struct vm_area_struct *vma)
{
    printk("<MICROS_MMAP> : I come in test_mmap function. \n");
	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 ret;
}  
//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
static long test_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
  printk("<MICROS_MMAP> : I come in test_ioctl function. \n");
  int result;
  int i;
	switch(cmd) 
	{	
	case 0:
	  {	
	  	result=0;
	  }			
	  break;
	case 1:
	  {	
	  	result=1;
	  }	
	break ;
	case 2:
	  {
           for(i=0;i<20;i++)
              {
              printk("i=%d  %c\n",i,*(testmap+i)); 
              }	
	  	result=2;
	  }
        break;	
	default:
		return -ENOTTY;			
	}
	return(result);
}	
static struct file_operations test_fs = {
	
	.owner 		= THIS_MODULE ,
	.open 		= test_open ,
	.release 	= test_close ,
	.read		= test_read ,
	.write		= test_write ,
	.mmap       = test_mmap,
	//.ioctl		= test_ioctl,
	.unlocked_ioctl = test_ioctl
};
static int	__init test_init(void)
{
	printk("<MICROS_MMAP> : -----------------------init-------------. \n");
	unsigned int 	ret ;
	unsigned char *virt_addr;
    memset(&test_dev , 0 ,sizeof(test_dev)) ;
	test_dev.dev_num = MKDEV(DRIVE_MAJOR , 0) ;
	ret = register_chrdev_region(test_dev.dev_num , 1 ,DRIVE_NAME) ;
	if(ret < 0)
	{
		return(ret) ;
	}

	cdev_init(&test_dev.cdev , &test_fs) ;
	test_dev.cdev.owner = THIS_MODULE ;
	test_dev.cdev.ops = &test_fs ;
	
	printk("\n<MICROS_MMAP> : Init drv \n") ;
		
	ret = cdev_add(&test_dev.cdev , test_dev.dev_num , 1) ;
	if(ret < 0)
	{
		printk("<MICROS_MMAP> : cdev add error !\n") ;
		return(ret) ;
	}

	testmap=kmalloc(4096,GFP_KERNEL);
	kmalloc_area=(int *)(((unsigned long)testmap +PAGE_SIZE-1)&PAGE_MASK);
	if(testmap==NULL)
	{
		printk("<MICROS_MMAP> : Kernel mem get pages error\n");
	} 
	for(virt_addr=(unsigned long)kmalloc_area;virt_addr<(unsigned long)kmalloc_area+4096;virt_addr+=PAGE_SIZE)
	{
		SetPageReserved(virt_to_page(virt_addr)); 
	}
	memset(testmap,'q',100); 

	printk("<MICROS_MMAP> : Test drv reg success !\n") ;
	return 0 ;
}
	

static void __exit test_exit(void)
{
	printk("<MICROS_MMAP> : Test drv  exit\n") ;
	cdev_del(&test_dev.cdev) ;
	unregister_chrdev_region(test_dev.dev_num , 1) ;
}
	

	
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");

 

//test.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#define  max_num  4096 
int main(int argc,char *argv[])
{
    int fd;
    int ret;
    unsigned char *rwc,*rrc;
    unsigned int *map;
    unsigned char ** newmap;
    rwc=malloc(sizeof(unsigned char));
    rrc=malloc(sizeof(unsigned char));
    *rwc=50;
    *rrc=30;
    fd=open("/dev/drvio1",O_RDWR);
    if(fd<0)
    	{
    		printf("open file error!\n");
    		return -1;
    	} 
    ret=write(fd,rwc,sizeof(rwc));
    ret=read(fd,rrc,sizeof(rrc));
    printf("rwc =%d\nrrc =%d\n",*rwc,*rrc);
    *rwc=10;
    ret=write(fd,rwc,sizeof(rwc));
    ret=read(fd,rrc,sizeof(rrc));
    printf("rwc =%d\nrrc =%d\n",*rwc,*rrc);
    ioctl(fd,2,0);
    if((map=(unsigned int *)mmap(NULL,max_num,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0))==MAP_FAILED)
       {
        printf("mmap error!\n"); 
       }
    memset(map,'c',max_num);
    strcpy(map,"Welcome");
    ioctl(fd,2,0);
    munmap(map,4096);
    map=NULL;
    close(fd);
    return 0;
}

 

MICROS_SOURCE = micros_mmap.c

LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)

obj-m +=micros_mmap.o
micros-objs := $(MICROS_SOURCE:.c=.o)

all:
	$(MAKE) -C $(LINUX_KERNEL_PATH)  M=$(PWD) modules

insmod:
	sudo insmod micros_mmap.ko

rmmod:
	sudo rmmod micros_mmap.ko

lsmod:
	lsmod | grep micros_mmap

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

生成一个设备节点

mknod /dev/drvio1 c 165 0

验证流程:

0. 创建一个新的虚拟字符设备drvio1,sudo mknod /dev/drvio1 c 165 0

1. 编译模块,在模块目录下执行make,得到micros_mmap.ko

2. 将模块导入内核使之生效:insmod micros_mmap.ko

3. 查看模块是否在内核中运行:lsmod |grep micros_mmap

4. 在核外进行测试,编译test.c得到可执行文件test: gcc -o test test.c

5. 运行test,查看结果

参考链接:https://blog.csdn.net/qvb3d/article/details/84276368?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值