Messages in this thread | | | Date | Tue, 21 Dec 2004 21:23:22 -0800 (PST) | From | John Wang <> | Subject | help on driver's nopage mmap method |
| |
Hi, I have been struggling for a couple of days about a problem of using nopage method to mmap memory from driver to user application.
What I try to do is very simple - just to get the simplest case to work, but I always get some junk in user app (to be more specific, always 0xFF in the mmap the memory area). I don't know what is wrong here - it appears perfectly normal (compared to the examples in the book Linux Device Driver). The kernel is 2.4.2 running on Intel x86 platform.
The program is very simple so I attached here (header includes are ignored here to shorten the length). Please CC me directly if anyone has answer since I am not subscribed to the mailing list. Thanks in advance.
<test user app> int main(int argc, char *argv[]) { int fd; char *addr; fd = open("/dev/my_mmap", O_RDONLY); if(fd < 0) { perror("open"); exit(1); } addr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0); if(addr == MAP_FAILED) { perror("mmap"); exit(1); } write(1, addr, 4096); return 0; }
<end of test user app>
<kernel driver> #define SOCK_MMAP_MAJOR 254 #define MY_NAME "mmap_sock" void mmap_sock_vma_open(struct vm_area_struct *vma) { printk("<1>%s called\n", __FUNCTION__); return; } void mmap_sock_vma_close(struct vm_area_struct *vma) { printk("<1>%s called\n", __FUNCTION__); return; } void *k_vaddr; struct page * mmap_sock_vma_nopage(struct vm_area_struct *vma, unsigned long address, int write_access) { struct page *pageptr; pageptr = virt_to_page(k_vaddr); get_page(pageptr); return pageptr; } static struct vm_operations_struct mmap_sock_vm_ops = { open: mmap_sock_vma_open, close: mmap_sock_vma_close, nopage: mmap_sock_vma_nopage, }; int mmap_sock_mmap(struct file* fp, struct vm_area_struct *vma) { size_t vma_size, pd_size; printk("<1>%s called\n", __FUNCTION__); if(vma->vm_pgoff != 0) { // this device has to be mapped from offset 0 return -EINVAL; } vma->vm_flags |= VM_RESERVED; vma->vm_ops = &mmap_sock_vm_ops; if(k_vaddr == NULL) { k_vaddr = __get_free_pages(GFP_KERNEL, 0); memset(k_vaddr, 0x30, PAGE_SIZE); } return 0; } int mmap_sock_open(struct inode *inode, struct file *fp) { if ( (fp->f_flags & O_ACCMODE) != O_RDONLY) { // only open for read return -EACCES; } return 0; } int mmap_sock_release(struct inode *inode, struct file *fp) { return 0; } static struct file_operations mmap_sock_fops = { open: mmap_sock_open, release: mmap_sock_release, mmap: mmap_sock_mmap, owner: THIS_MODULE, }; int init_module(void) { int ret = 0; ret = register_chrdev(SOCK_MMAP_MAJOR, MY_NAME, &mmap_sock_fops); if (ret < 0) { printk("<1>%s: can't get major %d\n", MY_NAME, SOCK_MMAP_MAJOR); return ret; } return 0; } void cleanup_module(void) { int ret; ret = unregister_chrdev(SOCK_MMAP_MAJOR, MY_NAME); if(ret < 0) { printk("<1>%s: can't unregister dev, err: %d\n", MY_NAME, ret); } }
__________________________________ Do you Yahoo!? Dress up your holiday email, Hollywood style. Learn more. http://celebrity.mail.yahoo.com - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |