The development environment of LDD3 recommended is 2.6.10, installed RHEL4-UPDATE4, its kernel version is 2.6.9.42, compiling the mmap program times wrong: Unknown symbol Remap_pfn_range
On the Internet, the above error should be changed to Remap_page_range, and Remap_page_range is no longer recommended, two kernel functions The second parameter definition is not the same:
int Remap_page_range (struct vm_area_struct *vma, unsigned long from, unsigned long phys_addr,// unsigned Long size, pgprot_t prot) int remap_pfn_range (struct vm_area_struct *vma, unsigned long addr, unsigned Long pfn,//Note and the above different unsigned long size, pgprot_t prot)
Look directly at the following section of the program, in the comments have been used to distinguish the use of two functions. Mknod/dev/mymap C 60 0 prior to use
#include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/ init.h> #include <linux/mm.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/ delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h># Include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/list.h > #include <linux/pci.h>//#include <linux/gpio.h> #define DEVICE_NAME "Mymap" static unsigned char array[ 10]={0,1,2,3,4,5,6,7,8,9};static unsigned char *buffer;static int my_open (struct inode *inode, struct file *file) {Retu RN 0;} static int my_map (struct file *filp, struct vm_area_struct *vma) {unsigned long page; unsigned char i; unsigned long start = (unsigned long) vma->vm_start; unsigned long end = (unsigned long) vma->vm_end; unsigned long size = (unsigned long) (Vma->vm_end-vma->vm_start); HaveTo the Physical Address page = Virt_to_phys (buffer); Maps a VMA virtual memory area of a user space to a contiguous physical page starting with page//if (Remap_pfn_range (vma,start,page>>page_shift,size,page_shared)) The third parameter is the page frame number, which is moved from the physical address to the right page_shift get if (Remap_page_range (vma,start,page,size,page_shared))//The third parameter is the page frame number, moved from the physical address to the right Page_ Shift gets return-1; Write 10 bytes of data for the memory for (i=0;i<10;i++) buffer[i] = Array[i]; return 0;} static struct File_operations Dev_fops = {. Owner = This_module,. Open = My_open,. mmap = My_map,};/*stat IC struct Miscdevice misc = {. minor = Misc_dynamic_minor,. Name = Device_name,. FoPs = &dev_fops,};*/static int __init dev_init (void) {int ret; Register Hybrid Device//ret = Misc_register (&misc); ret = Register_chrdev (device_name, &dev_fops); if (Ret < 0) {PRINTK ("<1> memory:can ' t obtain major number%d\n", 60); return ret; }//Memory allocation buffer = (unsigned char *) kmalloc (Page_size,gfp_kernel); Set the memory of the segment to reserved setpagereserved (vIrt_to_page (buffer)); return ret;} static void __exit dev_exit (void) {//Logoff device//misc_deregister (&MISC); Unregister_chrdev (device_name); Clear retention clearpagereserved (virt_to_page (buffer)); Free memory kfree (buffer);} Module_init (Dev_init); Module_exit (Dev_exit); Module_license ("Dual BSD/GPL");
Application:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include < fcntl.h> #include <linux/fb.h> #include <sys/mman.h> #include <sys/ioctl.h> #define Page_size 4096int Main (int argc, char *argv[]) { int fd; int i; unsigned char *p_map; Turn on the device FD = open ("/dev/mymap", O_RDWR); if (FD < 0) { printf ("Open fail\n"); Exit (1); } Memory map P_map = (unsigned char *) mmap (0, page_size, Prot_read | Prot_write, MAP_SHARED,FD, 0); if (P_map = = map_failed) { printf ("Mmap fail\n"); goto here; } Print the first 10 bytes of the mapped memory for (i=0;i<10;i++) printf ("%d\n", P_map[i]); Here: Munmap (P_map, page_size); return 0;}
Makefile File:
Obj-m: = testdrv.opwd : = $ (shell pwd) all:make-c/lib/modules/$ (Shell uname-r)/build m=$ (pwd) MODULESCLEAN:RM-RF *.O *~ core *.cmd *.mod.c./tmp_version
Linux device Drivers Remap_pfn_range () and Remap_page_range ()