"Turn" Linux device-driven mmap device operation

Source: Internet
Author: User

Original URL: http://www.cnblogs.com/geneil/archive/2011/12/08/2281222.html

1.mmap system Call

void *mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset);

Function: Responsible for mapping the contents of the file to the virtual address space of the process, by reading and modifying the memory to realize the reading and modification of the file, without having to call read and write again;
Parameter: Addr: The starting address of the map, set to NULL by the system designation;
Len: The length of the file mapped to memory;
Prot: Expected memory protection flag, cannot conflict with open mode of file. Prot_exec,prot_read,prot_write, etc.;
Flags: Specifies the type of the mapped object, and whether the mapping options and mapping pages can be shared. Map_shared,map_private, etc.;
FD: The file descriptor returned by open, representing the file to be mapped;
Offset: The migration of the file to begin mapping.
Return value: When executed successfully, MMAP () returns a pointer to the mapped area. On Failure, mmap () returns map_failed.

Mmap Mapping Diagram:

2. de-map:
int Munmap (void *start, size_t length);

3. Virtual Memory Area:
The virtual memory area is a homogeneous interval in the virtual address space of the process, that is, a contiguous address range with the same characteristics. The memory image of a process consists of the following parts: program code, data, BSS and stack areas, and memory-mapped regions.
The Linux kernel uses the VM_AREA_STRUCT structure to describe the virtual memory area. Its main members:

unsigned long vm_start; /* Our start address within VM_MM. * *
unsigned long vm_end; /* The first byte after our end address within VM_MM. * *
unsigned long vm_flags; /* Flags, see mm.h. The tag for the zone. such as Vm_io (the IO area marked as memory mapped by the VMA, prevents the system from including the zone in the process's storage dump) and vm_reserved (the flag memory area cannot be swapped out). */


4.mmap Device Operation:
Mapping a device refers to a segment of the user's space (the virtual address range) associated to the device memory, when the program reads and writes the address of this user space, it is actually accessing the device.
The Mmap method is a member of the file_operations struct that is called when the MMAP system call is issued. Until then, the kernel has done a lot of work.
The Mmap device method needs to do is to establish a virtual address to the physical address of the page table (virtual address and the physical address of the device Association through the page table).

static int mmap (struct file *file, struct vm_area_struct *vma);


Mmap How to complete the creation of the page table? (Two ways)
(1) Use Remap_pfn_range to create all page tables at once.

int Remap_pfn_range (struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot);
/**
* Remap_pfn_range-remap kernel memory to userspace
* @vma: User VMA to map to: virtual address range found by kernel
* @addr: Target user address to start at: virtual Address to associate
* @pfn: Physical Address of kernel memory: the physical location of the device to be associated, the physical frame number where the physical address is to be mapped, and the physical address >>page_shift
* @size: Size of map area
* @prot: page protection flags for this mapping
*
* Note:this is only safe if the mm semaphore are held when called.
*/


(2) Use Nopage VMA method to set up a page table each time;

5. Source Code Analysis:

(1) Memdev.h

View Code
/*MEM Device Description Structure Body */
struct MEM_DEV
{
Char *data;
unsigned long size;
};

#endif/* _memdev_h_ */

(2) MEMDEV.C

View Code
static int mem_major = Memdev_major;

Module_param (mem_major, int, s_irugo);

struct Mem_dev *mem_devp; /* Device Structural body pointer */

struct Cdev Cdev;

/* File Open function */
int Mem_open (struct inode *inode, struct file *filp)
{
struct Mem_dev *dev;

/* Get the secondary device number */
int num = MINOR (Inode->i_rdev);

if (num >= memdev_nr_devs)
Return-enodev;
dev = &mem_devp[num];

/* Assign the device description structure pointer to the file private data pointer */
Filp->private_data = Dev;

return 0;
}

/* File deallocation function */
int mem_release (struct inode *inode, struct file *filp)
{
return 0;
}
static int Memdev_mmap (struct file*filp, struct vm_area_struct *vma)
{
struct Mem_dev *dev = filp->private_data; /* Get the device structure pointer */

Vma->vm_flags |= Vm_io;
Vma->vm_flags |= vm_reserved;


if (Remap_pfn_range (Vma,vma->vm_start,virt_to_phys (dev->data) >>page_shift, VMA->VM_END-VMA->VM _start, Vma->vm_page_prot))
Return-eagain;

return 0;
}

/* File operation structure */
static const struct File_operations Mem_fops =
{
. Owner = This_module,
. open = Mem_open,
. Release = Mem_release,
. mmap = Memdev_mmap,
};

/* Device driver module load function */
static int memdev_init (void)
{
int result;
int i;

dev_t Devno = MKDEV (mem_major, 0);

/* Static application device number */
if (mem_major)
result = Register_chrdev_region (Devno, 2, "Memdev");
else/* Dynamically assign device number */
{
result = Alloc_chrdev_region (&devno, 0, 2, "Memdev");
Mem_major = Major (Devno);
}

if (Result < 0)
return result;

/* Initialize the CDEV structure */
Cdev_init (&cdev, &mem_fops);
Cdev.owner = This_module;
Cdev.ops = &mem_fops;

/* Register character device */
Cdev_add (&cdev, MKDEV (mem_major, 0), Memdev_nr_devs);

/* Allocate memory for device description structure */
MEM_DEVP = Kmalloc (Memdev_nr_devs * sizeof (struct mem_dev), gfp_kernel);
if (!MEM_DEVP)/* Request failed */
{
result =-Enomem;
Goto Fail_malloc;
}
memset (MEM_DEVP, 0, sizeof (struct mem_dev));

/* Allocate memory for device */
for (i=0; i < Memdev_nr_devs; i++)
{
Mem_devp[i].size = memdev_size;
Mem_devp[i].data = Kmalloc (memdev_size, Gfp_kernel);
memset (mem_devp[i].data, 0, memdev_size);
}

return 0;

Fail_malloc:
Unregister_chrdev_region (Devno, 1);

return result;
}

/* Module Unload function */
static void Memdev_exit (void)
{
Cdev_del (&cdev); /* Unregister the device */
Kfree (MEM_DEVP); /* release device structure in vivo */
Unregister_chrdev_region (MKDEV (mem_major, 0), 2); /* Release the device number */
}

Module_author ("David Xie");
Module_license ("GPL");

Module_init (Memdev_init);
Module_exit (Memdev_exit);

(3) App-mmap.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main ()
{
int FD;
Char *start;
Char buf[100];
Char *buf;

/* Open File */
FD = open ("/dev/memdev0", O_RDWR);

BUF = (char *) malloc (100);
memset (buf, 0, 100);
Start=mmap (null,100,prot_read| prot_write,map_shared,fd,0);

/* read out the data */
strcpy (Buf,start);
Sleep (1);
printf ("Buf 1 =%s\n", buf);

/* Write Data */
strcpy (Start, "Buf is not null!");

memset (buf, 0, 100);
strcpy (Buf,start);
Sleep (1);
printf ("Buf 2 =%s\n", buf);


Munmap (start,100); /* de-map */
Free (BUF);
Close (FD);
return 0;
}


Test steps:

(1) Compile and install kernel module: Insmod Memdev.ko

(2) View device name, main device number: Cat/proc/devices

(3) Manually create device node: Mknod /dev/memdev0 c * * * 0

To see if a device file exists: Ls-l/dev/* | grep Memdev

(4) Compile the download to run the application:./app-mmap

Results: buf 1 =

BUF 2 = buf is not null!

Summary: The MMAP device method realizes that the memory of the user space is connected to the memory of the device, the reading and writing of the user space is equivalent to the reading and writing of the character device, not all devices can be mmap abstracted, such as serial port and other flow-oriented devices cannot do mmap abstraction.

"Turn" Linux device-driven mmap device operation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.