⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmap.c

📁 Linux设备驱动的经典教材, 该电子书是第三版,并附有全部配套代码.
💻 C
字号:
/*  -*- C -*- * mmap.c -- memory mapping for the sculld char module * * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.  The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates.   No warranty is attached; * we cannot take responsibility for errors or fitness for use. * * $Id: _mmap.c.in,v 1.13 2004/10/18 18:07:36 corbet Exp $ */#include <linux/config.h>#include <linux/module.h>#include <linux/mm.h>		/* everything */#include <linux/errno.h>	/* error codes */#include <asm/pgtable.h>#include "sculld.h"		/* local definitions *//* * open and close: just keep track of how many times the device is * mapped, to avoid releasing it. */void sculld_vma_open(struct vm_area_struct *vma){	struct sculld_dev *dev = vma->vm_private_data;	dev->vmas++;}void sculld_vma_close(struct vm_area_struct *vma){	struct sculld_dev *dev = vma->vm_private_data;	dev->vmas--;}/* * The nopage method: the core of the file. It retrieves the * page required from the sculld device and returns it to the * user. The count for the page must be incremented, because * it is automatically decremented at page unmap. * * For this reason, "order" must be zero. Otherwise, only the first * page has its count incremented, and the allocating module must * release it as a whole block. Therefore, it isn't possible to map * pages from a multipage block: when they are unmapped, their count * is individually decreased, and would drop to 0. */struct page *sculld_vma_nopage(struct vm_area_struct *vma,                                unsigned long address, int *type){	unsigned long offset;	struct sculld_dev *ptr, *dev = vma->vm_private_data;	struct page *page = NOPAGE_SIGBUS;	void *pageptr = NULL; /* default to "missing" */	down(&dev->sem);	offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);	if (offset >= dev->size) goto out; /* out of range */	/*	 * Now retrieve the sculld device from the list,then the page.	 * If the device has holes, the process receives a SIGBUS when	 * accessing the hole.	 */	offset >>= PAGE_SHIFT; /* offset is a number of pages */	for (ptr = dev; ptr && offset >= dev->qset;) {		ptr = ptr->next;		offset -= dev->qset;	}	if (ptr && ptr->data) pageptr = ptr->data[offset];	if (!pageptr) goto out; /* hole or end-of-file */	/* got it, now increment the count */	get_page(page);	if (type)		*type = VM_FAULT_MINOR;  out:	up(&dev->sem);	return page;}struct vm_operations_struct sculld_vm_ops = {	.open =     sculld_vma_open,	.close =    sculld_vma_close,	.nopage =   sculld_vma_nopage,};int sculld_mmap(struct file *filp, struct vm_area_struct *vma){	struct inode *inode = filp->f_dentry->d_inode;	/* refuse to map if order is not 0 */	if (sculld_devices[iminor(inode)].order)		return -ENODEV;	/* don't do anything here: "nopage" will set up page table entries */	vma->vm_ops = &sculld_vm_ops;	vma->vm_flags |= VM_RESERVED;	vma->vm_private_data = filp->private_data;	sculld_vma_open(vma);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -