mmap内核空间映射结合kfifo,poll机制的实现例子

平台:
	全志A20
	Android4.2.2 Linux3.4
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include //定义virt_to_phys接口  
#include //remap_pfn_range  

#define FIFO_SIZE  128
static int DEV_MAJOR = 1222;
static int DEV_MINOR = 0;

static struct class *cdrv_class;
static struct device *cdrv_class_dev;
static struct cdev *c_cdev;
static char *buff;
#if 0
typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) c_fifo;
static c_fifo cdrv_fifo;
#else 
struct kfifo_rec_ptr_1 cdrv_fifo;
#endif

static const char *expected_buff1[] = {
			"aaaaaaaaaa",
			"bbbbbbbbbb",
			"cccccccccc",
			"dddddddddd",
			"eeeeeeeeee",
			"ffffffffff",
			"gggggggggg",
			"hhhhhhhhhh",
};
static const char *expected_buff2[] = {
			"iiiiiiiiii",
			"jjjjjjjjjj",
			"kkkkkkkkkk",
			"llllllllll",
			"mmmmmmmmmm",
			"nnnnnnnnnn",
			"oooooooooo",
			"pppppppppp",
};
static const char *expected_buff3 = "abcdefghijk";
static const char *expected_buff4 = "lmnopqrstuvwxyz";
#define pagesSIZE 4096
static wait_queue_head_t creadq;
static int flag = 0;
static int wakeMe = 0;
static struct task_struct *tsk;


static int c_open(struct inode *inode,struct file *filp){
	
	//filp->private_data = buff;
	buff = (char *)kmalloc(pagesSIZE,GFP_KERNEL);	
	if(!buff){
		printk("kmalloc err \n");
		return -1;
	}
	memset(buff,'\0',pagesSIZE);
	return 0;	
}

static int c_release(struct inode *inode,struct file *filp){
	 
	if(buff){  
        kfree(buff);  
    }  
	return 0;
}

static ssize_t c_read(struct file *filp,char *buf,size_t len,loff_t *off){
#if 0	
	if(copy_to_user(buf,filp->private_data,strlen(filp->private_data))){
		return -EFAULT;
	}
#else
	int ret;
	unsigned int copied;
	ret = kfifo_to_user(&cdrv_fifo,buf,len,&copied);
	
	return sizeof(filp->private_data);
#endif	
	return ret?ret:copied;
}

static ssize_t c_write(struct file *filp,const char *buf,size_t len,loff_t *off){
#if 0
	memset(filp->private_data,0,strlen(filp->private_data));	
	if(copy_from_user(filp->private_data,buf,strlen(buf))){
		return -EFAULT;
	}
	
	return sizeof(buf);
#else
	int ret;
	unsigned int copied;
	
	ret = kfifo_from_user(&cdrv_fifo,buf,len,&copied);
	return ret?ret:copied;
#endif
}
#if 0
static int fifo_handler(void){
	int i;
	
	for(i=0;ivm_flags |= VM_IO;
    vma->vm_flags |= VM_RESERVED;
	 if(remap_pfn_range(vma,//虚拟内存区域,即设备地址将要映射到这里  
                       vma->vm_start,//虚拟空间的起始地址  
                       virt_to_phys(buff)>>PAGE_SHIFT,//与物理内存对应的页帧号,物理地址右移12位  
                       vma->vm_end - vma->vm_start,//映射区域大小,一般是页大小的整数倍  
                       vma->vm_page_prot))//保护属性,  
    {  
        return -EAGAIN;  
    } 	
	//memcpy((void *)buff,"dddddd8",8);
	return 0;
}
static int isReadyToWakeup(void *data){
	int i,ret;
	printk("kthread is in \n");
	for(i=0;iops = &c_fops;
	c_cdev->owner = THIS_MODULE;	
	
	err = cdev_add(c_cdev,devno,1);	
	if(err<0){
		printk("cdev_add err \n");
		goto cdev_add_err;
	}
	
	
	cdrv_class = class_create(THIS_MODULE,"c_drv");
	cdrv_class_dev = device_create(cdrv_class,NULL,MKDEV(DEV_MAJOR,DEV_MINOR),NULL,"cdrv-%d",0);
	if(!cdrv_class_dev){
		printk("device create err  \n");
		goto device_create_err;
	}
	init_waitqueue_head(&creadq);
#if 0
	INIT_KFIFO(cdrv_fifo);
#else 
	err = kfifo_alloc(&cdrv_fifo, FIFO_SIZE, GFP_KERNEL);  
    if (ret) {  
        printk(KERN_ERR "error kfifo_alloc\n");  
        goto kfifo_alloc_err;  
    }
#endif
	
#if 0		
	err = fifo_handler();
	if(err){
		printk("fifo_handler err  \n");
		return err;
	}	
#endif
	tsk = kthread_run(isReadyToWakeup,NULL,"thread_isReadyToWakeup");
	if(NULL == tsk){
			printk("kthread created failed  \n");
			goto kthread_run_err;
	}
	printk("init is ok \n\n");
	return 0;
	
kthread_run_err:
	kfifo_free(&cdrv_fifo);
kfifo_alloc_err:
	device_unregister(cdrv_class_dev);
device_create_err:
	class_destroy(cdrv_class);
	cdev_del(c_cdev);
cdev_add_err:
	kfree(c_cdev);
cdev_alloc_err:
	unregister_chrdev_region(devno,1); 
	return err;
}

static void __exit c_exit(void){
	dev_t devno = MKDEV(DEV_MAJOR,DEV_MINOR);	
	if(tsk){
        kthread_stop(tsk);
    }
	kfifo_free(&cdrv_fifo);
	device_unregister(cdrv_class_dev);
	class_destroy(cdrv_class);
	cdev_del(c_cdev);
	kfree(c_cdev);
	unregister_chrdev_region(devno,1);  
}

module_init(c_init);
module_exit(c_exit);
MODULE_LICENSE("GPL");

用户测设程序:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MBUFF_SIZE 20
int main()
{
	char *mbuff;
        int fd,i;
	fd_set rfds;
	struct timeval tv;
	
        fd=open("/dev/cdrv-0",O_RDWR,S_IRUSR | S_IWUSR);
        if(fd == -1){
		perror("open");
		return -1;
	}


		mbuff = mmap(NULL,MBUFF_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
		if(mbuff != NULL){
			printf("mbuff:  %p \n",mbuff);
			//puts(mbuff);
		}
		else{
			puts("mbuff: err");
			return -1;
		}
	
	while(1){
		FD_ZERO(&rfds);
		FD_SET(fd,&rfds);
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		select(fd+1,&rfds,NULL,NULL,&tv);//最后一个参数设为NULL,将会永远等待,即阻塞!
		if(FD_ISSET(fd,&rfds)){ 
			puts("The new data is:");
			puts(mbuff);
		//	memset(mbuff,'\0',MBUFF_SIZE);
		}else{
			printf("No data within 5s,please wait.. \n",&tv.tv_sec);
		}
		sleep(3);	
	}
	




	munmap(mbuff,MBUFF_SIZE);
        close(fd);
        return 0;


}
测试截图:


你可能感兴趣的:(android)