この質問で説明したように、カーネルのブートパラメータを使用してブート時にメモリチャンクを予約していますmemmap=8G$64G
私は、初期化中にこの予約済みメモリチャンクのioremapを実行する文字ドライバカーネルモジュールを作成しました。ここで
説明したように、私のドライバーでは、によって返されるこのメモリチャンクポインタに対して行う必要があるのは。mmap
remap_pfn_range
ioremap
私はこれを3.0Linuxカーネルで実行しています。私のユーザースペースアプリケーションは、ドライバーによってマウントされたデバイスとしてこのメモリチャンクを開きます。使用スペースアプリケーションから実行 すると、システムがハングmmap
するのがわかります。私は私に多くの情報を提供しません。dmesg
入力はありますか?
static int __init myDev_module_init(void)
{
int retval;
myDev_major = register_chrdev(0, DEVICE_NAME, &myDevfops);
if (myDev_major < 0)
{
err("failed to register device: error %d\n", myDev_major);
retval = myDev_major;
goto FAILED_CHRDEVREG;
}
myDev_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(myDev_class))
{
err("failed to register device class '%s'\n", CLASS_NAME);
retval = PTR_ERR(myDev_class);
goto FAILED_CLASSREG;
}
myDev_device = device_create(myDev_class, NULL, MKDEV(myDev_major, 0), NULL, CLASS_NAME "_" DEVICE_NAME);
if (IS_ERR(myDev_device))
{
err("failed to create device '%s_%s'\n", CLASS_NAME, DEVICE_NAME);
retval = PTR_ERR(myDev_device);
goto FAILED_DEVREG;
}
ここで、myDev.startOffset
は#define
d64GBとmyDev.memSize
8GBに初期化されます。
//myDev.startAddr = ioremap(myDev.startOffset,myDev.memSize);
//memset_io(myDev.startAddr, 0, myDev.memSize);
return 0;
FAILED_DEVREG:
class_unregister(myDev_class);
class_destroy(myDev_class);
FAILED_CLASSREG:
unregister_chrdev(myDev_major, DEVICE_NAME);
FAILED_CHRDEVREG:
return -1;
}
static int myDev_device_open(struct inode* inode, struct file* filp)
{
dbg("");
if ( ((filp->f_flags & O_ACCMODE) == O_WRONLY) || ((filp->f_flags & O_ACCMODE) == O_RDWR) )
{
warn(" Opening the device with write access\n");
//return -EACCES;
}
info(" device Open is called\n");
filp->private_data = &myDev;
return 0;
}
そして、それmmap
はかなり簡単です。
static int myDev_device_mmap(struct file * f, struct vm_area_struct * vma)
{
int retval = 0;
struct myDevDev * pDev = (struct myDevDev *)(f->private_data);
dbg("");
if(vma)
{
if(f)
{
if(f->private_data)
warn("mmap: f->private_data : %p\n", f->private_data);
else
warn(" mmap :f->private_data : NULL \n");
}
else
{
warn("mmap: f :NULL\n");
}
warn(": mmap: vm start : %lu\n", vma->vm_start);
warn(" mmap: vm end : %lu\n", vma->vm_end);
warn(" mmap: vm pg offset : %lu\n", vma->vm_pgoff);
//retval = remap_pfn_range(vma, vma->vm_start, pDev->startOffset >> PAGE_SHIFT, pDev->memSize, PAGE_SHARED) ;
// retval = remap_pfn_range(vma, vma->vm_start, pDev->startAddr >> PAGE_SHIFT, pDev->memSize, PAGE_SHARED) ;
//retval = remap_pfn_range(vma,pDev->startAddr ,pDev->startOffset >> PAGE_SHIFT, pDev->memSize, PAGE_SHARED);
retval = remap_pfn_range(vma,vma->vm_start ,pDev->startOffset >> PAGE_SHIFT, pDev->memSize, PAGE_SHARED);
if(retval <0)
{
warn(" ERROR : in mapping kernel virtual space to user space return value : %d \n",retval);
return -EINVAL;
}
//if(0)
{
vma->vm_flags |=VM_LOCKED;
vma->vm_ops = &myRemapVMOps;
vma->vm_flags |= VM_RESERVED;
vma->vm_private_data = f->private_data;
myDevice_VMA_Open(vma);
}
}
else
{
warn ("vma is NULL");
}
dbg(" Done ");
warn("mmpaing done : \n");
return 0;
}
私のユーザースペースアプリケーションから、私は次のことを行っています:
int err, i=0;
void * mptr = NULL;
printf(" Access the reserved memory chunk \n ");
int fd = open("/dev/myDevice", O_RDWR | O_SYNC);
if(fd <=0)
{
printf("ERROR: my device driver is not loaded \n");
return 1;
}
printf("\n mmaping mem chunk size :%llu pagesize :%lu input mptr :%p\n", sz,getpagesize (), mptr);
mptr = mmap(0, sz , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0);
if(mptr == MAP_FAILED)
{
close(fd);
perror("Error mmapping the file");
printf("\nmmapped mem address %p\n",mptr);
exit(1);
}
printf("\nmmapped mem address %p\n",mptr);
//char * ptr = (char *)mptr;
//*ptr = 'a';
//int * pInt = (int *) (((char *) mptr)+1);
//for(;i<10000; ++i)
{
// pInt[i] = 2*i;
}
/* free the mmapped memory
*/
if (munmap(mptr, sz) == -1)
{
perror("Error un-mmapping the file");
}
close(fd);
観察 :
(vma->vm_end - vma->vm_start)
どういうわけか常に4Kのサイズが反映されていないようです。