Reputation: 33
I am trying to map a kernel buffer in user space using mmap method in linux 3.10.10. But it is returning MAP_FAILED
. Why it is failed to map the buffer.
Kernel module
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <linux/init.h> /* Needed for the macros */
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <linux/io.h>
//#include <linux/malloc.h>
#include <linux/mm.h> /* mmap related stuff */
long long *buf1;
long long* buf;
static int driver_mmap(struct file *file, struct vm_area_struct *vma)
{
vma->vm_flags |= VM_LOCKED|VM_SHARED;
int i = remap_pfn_range(vma, vma->vm_start,
virt_to_phys(buf) >> PAGE_SHIFT,
vma->vm_end-vma->vm_start, vma->vm_page_prot);
SetPageReserved(virt_to_page(buf));
printk("MMAP \n");
return 0;
}
struct file_operations proc_fops =
{
mmap:driver_mmap,
};
int init_module_test(void)
{
int i;
buf1 = kmalloc(4096, __GFP_COLD|GFP_DMA);
buf = ((int)buf1 + PAGE_SIZE -1) & PAGE_MASK;
printk("<1>Hello world1\n");
for (i = 0; i < 512; i++)
{
buf[i] = (long long) i + 1;
}
proc_create ("mmap_example",0,NULL, &proc_fops);
printk("<1>Hello world3\n");
printk("<1>BUF1 = 0x%08x\n BUF = 0x%08x\n", buf1,buf);
return 0;
}
void cleanup_module_test(void)
{
remove_proc_entry ("mmap_example", NULL);
kfree(buf1);
printk("Goodbye world\n");
}
module_init(init_module_test);
module_exit(cleanup_module_test);
Application code
#include<stdio.h>
#include<stdlib.h>
#include<sys/mman.h>
int main(void)
{
int fd, i;
long long *msg = NULL;
if ((fd = fopen("/proc/mmap_example", "r")) < 0)
{
printf("File not opened");
}
msg = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
if (msg == MAP_FAILED)
{
printf("MAP failed");
return 0;
}
for (i = 0; i < 512; i++)
printf("0x%llx,", msg[i]);
fclose(fd);
return 0;
}
I always end up seing "MAP failed"
.
Is there something wrong with my code?
Upvotes: 1
Views: 3722
Reputation: 384234
debugfs can't handle mmap
I know this is not your exact case, but it also makes mmap
fail with MAP_FAILED
, and it may help future Googlers: https://patchwork.kernel.org/patch/9252557/
And here is a fully working procfs example with an userland test.
Upvotes: 0
Reputation: 12357
The first problem is that you are attempting to use fopen
to open a file and placing the return value in an integer, but fopen
doesn't return an integer. It returns FILE *
. This tells me you are ignoring compiler warnings and errors. That's a bad idea: they're produced for a reason.
The second problem is that you actually do need an integer file handle in order to provide it as an argument to mmap(2)
. For that, you should be calling open(2)
(not fopen(3)
).
There may well be additional problems with this code, but that's a start.
Upvotes: 2
Reputation: 343
well, i can't comment so i post an answer that is not one, but i hope it will be still useful:
i'm not sure about the driver, but you can use the errno method (http://man7.org/linux/man-pages/man3/errno.3.html) on mmap to have a better answer on why it's failing:
add in your application code at the right place:
#include <errno.h>
printf("%i",errno);
or you could maybe use the following if you don't want to print the errno :
cpp -dM /usr/include/errno.h | grep 'define E' | sort -n -k 3
from How to know what the 'errno' means?
Upvotes: 1