}
做了一个外挂lcd模块的驱动,在内核区用kmalloc申请了(1 * PAGE_SIZE)的物理内存作为lcd数据帧缓冲,通过remap_pfn_range建立和用户空间的页表映射,在应用程序中使用mmap系统调用返回映射的用户虚拟内存的地址*ret;在用户空间向ret中写入要显示的图片,通过ioctl系统调用命令通知内核刷显lcd模块;问题:第一次用户更新ret后,内核空间对应的虚拟内存映射区可已得到实时更新,调用ioctl刷显图片正常;但再次更新用户空间ret缓冲后,在内核空间对应缓冲更新不实时,ioctl刷显后部分花屏,花屏区属于上次图片的显示数据;每次在用户空间更新ret显示缓冲后,需要等2秒以上的时间,再调用ioctl刷显才能正常刷屏;用户空间和内核空间的虚拟内存缓冲映射后对应的是同一块物理内存,问什么更新效率这么低呢??求高人帮忙!!!
部分用户应用代码:
int main()
{
int fd = 0;
unsigned long ch=0;
fd = open("/dev/lcd160dev0",O_RDWR|O_SYNC);
if(fd<0)
{
perror("fail open");
return -1;
}
ret = mmap(NULL, lcd_buff_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, fd, 0 );
if( ret == MAP_FAILED )
{
perror("fail mmap");
return -1;
}
ioctl(fd, IOCTL_LCD_CMD_ON, 0);
memcpy( ret, DISPLOGO1, 3200 );
ioctl(fd, IOCTL_LCD_CMD_UPDATE, 0);
部分驱动源码:
unsigned char *lcd_data_buff = NULL;
static void my_vm_open(struct vm_area_struct *vma)
{
printk("VMA open\n");
}
static void my_vm_close(struct vm_area_struct *vma)
{
printk("VMA close.\n");
}
struct vm_operations_struct vm_ops =
{
.open = my_vm_open,
.close = my_vm_close,
};
static int lcd_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int i=0;
switch (cmd)
{
case IOCTL_LCD_CMD_ON:
lcd_initialize();
LCD_BL_ON();
printk(KERN_INFO "kernel lcd init success! \n");
break;
case IOCTL_LCD_CMD_OFF:
break;
case IOCTL_LCD_CMD_RESTOR:
break;
case IOCTL_LCD_CMD_UPDATE:
write_screen_data();
printk(KERN_INFO "kernel lcd UPDATE success!! \n");
break;
default:
printk("Ioctl mode not support\n");
}
return 0;
}
static int my_mmap(struct file *flip,struct vm_area_struct *vma)
{
unsigned long physics,mypfn,vmsize;
printk("in mmap\n");
physics = virt_to_phys((void *)lcd_data_buff);
mypfn = physics >> PAGE_SHIFT;
vmsize = vma->vm_end-vma->vm_start;
if(vmsize > lcd_buff_size)
return -ENXIO;
if(remap_pfn_range(vma,vma->vm_start,mypfn,vmsize,vma->vm_page_prot))
return -EAGAIN;
vma->vm_ops = &vm_ops;
my_vm_open(vma);
return 0;
}
static int my_open(struct inode *inode ,struct file *flip)
{
printk("open file sucess\n");
return 0;
}
static int my_release(struct inode *inode ,struct file *flip)
{
printk("release file sucess\n");
return 0;
}
struct file_operations fops={
.owner = THIS_MODULE,
.open = my_open,
.release = my_release,
.ioctl= lcd_ioctl,
.mmap = my_mmap,
};
经进一步测试,每次通过系统调用进入内核态对映射区进行读操作后(即使是一个字节的操作),待返回用户应用程序后刷新映射区,再次系统调用进入内核态操作映射区就会发现数据更新不同步(大约需等2秒后正常更新);若进入内核态不对映射区进行操作,则数据更新正常,用户内核数据更新同步(测试方法:在用户态连续刷5张不同的图片数据,每次刷过后系统调用进入内核但不操作映射区返回,在第五次刷图片后系统调用将内核映射区的数据打印输出,则更新正常;若每次系统调用对内核映射进行操作,则最后一次输出数据乱);请求大侠指点一二!!!