微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Linux内核模块mmap函数无法正常工作

我正在为pcie编写内核驱动程序,为此我需要将大小为4KB的缓冲区从用户空间映射到内核空间。 首先使用kzalloc()在内核模块初始化时分配一个缓冲区,并初始化为0xff。 这个缓冲区的指针然后用在内核端的mmap实现中。 问题是,在用户空间应用程序调用mmap之后,将缓冲区写入csv文件以检查映射是否已正确完成,但是文件显示的某些区域的值正确(0xffffffff),而某些垃圾随机很小这部分如下所示:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF ffffffff 006bafdf 00000008 006c9fdf 00000008 00000000 00000000 006c1fdf

而根据我的理解,映射后所有的位置应该已被打印为0xffffffff。 这是造成问题,因为我需要用这个用户应用程序的数据填充这个缓冲区,并给驱动模块发送信号,以便它可以使用writel()函数通过pcie传输数据。 映射的内核端代码如下所示:

static int driver_mmap5(struct file *file,struct vm_area_struct *vma) { int ret; vma->vm_flags |= VM_LOCKED|VM_SHARED; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys(TEST5) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,vma->vm_page_prot); if(ret != 0) printk("MMAP Failed n"); SetPageReserved(virt_to_page(TEST5)); #ifdef DEBUG printk("MMAP Succeeded n"); #endif return 0; }

其中TEST5是指向要映射的缓冲区的指针,分配如下:

Linux中所有的挂载点在哪里?

在windows 7和msvc下编译QT 5.3.2

将BITMAP转换为HBITMAP

什么是更好的方式来宣布在基于arm的拱门上的标志?

SYstem进程可以与非SYstem进程共享数据吗?

long *TEST5; TEST5 = kzalloc(PB_BUFF_SIZE,__GFP_COLD|GFP_DMA); memset(TEST5,0xff,PB_BUFF_SIZE)

用户空间应用程序中,分配和映射另一个缓冲区,如下所示:

unsigned long* msg5; msg5=(unsigned long*)malloc(PB_BUFF_SIZE);

调用mmap:

msg5 = mmap(NULL,PB_BUFF_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);

看来映射有一些问题,因为有些部分被映射,有些不是,因此是不正确的值。 请提出这个问题的原因和解决办法。

问候,

编辑:添加下面的驱动程序和应用程序端的相关代码

驱动程序缓冲区映射的代码

long *TEST5; #define PB_BUFF_SIZE 8192 static int driver_mmap5(struct file *file,vma->vm_page_prot); if(ret != 0) printk("MMAP Failed n"); SetPageReserved(virt_to_page(TEST5)); #ifdef DEBUG printk("MMAP Succeeded n"); #endif return 0; } struct file_operations proc_fops5 = { //.read = read_proc,.write = write_proc5,.mmap = driver_mmap5,}; static void create_new_proc_entries(void) { proc_create ("PCI_PICOZED_Param5",NULL,&proc_fops5); printk(KERN_DEBUG "Proc entries created successfullyn"); } static void Delete_proc_entries(void) { remove_proc_entry ("PCI_PICOZED_Param5",NULL); printk(KERN_DEBUG "Proc entries removed successfullyn"); } static int __init pci_skel_init(void) { TEST5 = kzalloc(PB_BUFF_SIZE,PB_BUFF_SIZE);//test with mem printk("memset array okn"); //adding print of few buffer values int i=0; for(i=0;i<20;i++) printk("alloc TEST5[%d]=%.8lx,add=%.lxn",i,TEST5[i],TEST5+i);//should be 0xff return 1; } static void __exit pci_skel_exit(void) { Delete_proc_entries(); kfree(TEST5); } module_init(pci_skel_init); module_exit(pci_skel_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Malik"); MODULE_DEVICE_TABLE(pci,PCI_ID_K);

应用程序代码缓冲区映射和testing

#include<stdio.h> #include<stdlib.h> #include<fcntl.h> #include <unistd.h> #include <signal.h> #include<errno.h> #include<sys/mman.h> #include<string.h> #define PB_BUFF_SIZE 8192 unsigned long *msg5 = NULL; int main(int argc,char *argv[])//adding cmd line arguments to control the operating mode { int mode=0; //mode 1 for VDM,mode 2 for playback if(argc==2) { mode=atoi(argv[1]); printf("The operating mode is %dn",mode); } else { mode=1;//default mode VDM } int fd,i; char str [10]; //msg5=(unsigned long*)malloc(PB_BUFF_SIZE); //Now commented as mmap returns allocated memory //buffer mapping if((fd=open("/proc/PCI_PICOZED_Param5",O_RDWR )) <0)//open("/proc/PCI_PICOZED_Param",O_RDONLY ) { printf("File not opened "); } printf("fd PCI_PICOZED_Param5 openedn"); msg5 = mmap(NULL,0); if(msg5==MAP_Failed) { printf("MAP Failed and error is %s",strerror(errno)); return 0; } close(fd); fd=open("Init_check_msg5.csv",O_CREAT | O_RDWR ); for(i=0;i < PB_BUFF_SIZE/4 ;i++) { //fprintf(bf,"%.8lxn",msg5[i]); sprintf(stri,msg5[i]); write(fd,stri,20); } close(fd); return 0 }

然后检查csv文件中的值,其显示如上所述的行为。

fork + exec无需atfork处理程序

如何加快我的记忆扫描程序?

通过分叉减轻内存泄漏

什么是IconnectionPoint和EventHandling

如何使用另一个C ++程序编译C ++代码

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐