Linux设备驱动remap_pfn_range() 和remap_page_range()

LDD3的开发环境推荐的是2.6.10,安装了RHEL4-update4,其内核版本为2.6.9.42,编译mmap的程序时报错:Unknown symbol remap_pfn_range

在网上查了下,应将上述报错的函数改为remap_page_range,并且remap_page_range不再推荐使用了,两个内核函数第二个参数定义不相同:

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,		//注意和上述的不同
            unsigned long size,
            pgprot_t prot)	

直接看下面的一段程序,在注释中已经将两个函数的使用区分出来了。使用前,先mknod /dev/mymap c 60 0

#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)
{
    return 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);

    //得到物理地址
    page = virt_to_phys(buffer);
    //将用户空间的一个vma虚拟内存区映射到以page开始的一段连续物理页面上
    //if(remap_pfn_range(vma,start,page>>PAGE_SHIFT,size,PAGE_SHARED))//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到
	if(remap_page_range(vma,start,page,size,PAGE_SHARED))//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得到
        return -1;

    //往该内存写10字节数据
    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,
};

/*
static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};
*/

static int __init dev_init(void)
{
    int ret;    

    //注册混杂设备
    //ret = misc_register(&misc);

	ret = register_chrdev(60, DEVICE_NAME, &dev_fops);
    if (ret < 0)
	{
            printk("<1> memory: can't obtain major number %d\n", 60);
            return ret;
    }

    //内存分配
    buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);
    //将该段内存设置为保留
    SetPageReserved(virt_to_page(buffer));

    return ret;
}

static void __exit dev_exit(void)
{
    //注销设备
    //misc_deregister(&misc);
	 unregister_chrdev(60, DEVICE_NAME);

    //清除保留
    ClearPageReserved(virt_to_page(buffer));
    //释放内存
    kfree(buffer);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("Dual BSD/GPL");

应用程序:

#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 4096

int main(int argc , char *argv[])
{
    int fd;
    int i;
    unsigned char *p_map;

    //打开设备
    fd = open("/dev/mymap",O_RDWR);
    if(fd < 0)
    {
        printf("open fail\n");
        exit(1);
    }

    //内存映射
    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;
    }

    //打印映射后的内存中的前10个字节内容
    for(i=0;i<10;i++)
        printf("%d\n",p_map[i]);

here:
    munmap(p_map, PAGE_SIZE);
    return 0;
}

makefile文件:

obj-m := testdrv.o
PWD       := $(shell pwd)
all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
	rm -rf *.o *~ core .*.cmd *.mod.c ./tmp_version
时间: 2024-11-06 01:16:31

Linux设备驱动remap_pfn_range() 和remap_page_range()的相关文章

Linux设备驱动核心理论(三)

10.中断与时钟 10.1 中断与定时器 所谓中断是指CPU在执行程序的过程中,出现了某些突发事件急待处理,CPU必须暂停执行当前程序,转去处理突发事件,处理完毕后CPU又返回原程序被中断的位置并继续执行. 根据中断的来源,中断可分为内部中断和外部中断,内部中断的中断来源来自CPU内部(软件中断.溢出.除法错误等,例如,操作系统从用户态切换到内核态需借助CPU内部的软件中断),外部中断的中断来源来自CPU外部,由外设提出请求. 根据中断是否可以屏蔽分为可屏蔽中断与不屏蔽中断(NMI),可屏蔽中断

Linux 设备驱动 Edition 3

原文网址:http://oss.org.cn/kernel-book/ldd3/index.html Linux 设备驱动 Edition 3 By Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman 由 quickwhale 翻译的简体中文版 V0.1.0 2006-6-2 遵循原版的版权声明. 还在完善中. 欢迎任何意见, 请给我邮件. 请发信至 quickwhale 的邮箱 <[email protected]> 版权 ©

linux设备驱动第五篇:驱动中的并发与竟态

综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被执行.而并发的执行单元对共享资源(硬件资源和软件上的全局.静态变量)的访问则容易导致竞态(race conditions).可能导致并发和竟态的情况有: SMP(Symmetric Multi-Processing),对称多处理结构.SMP是一种紧耦合.共享存储的系统模型,它的特点是多个CPU使用共

Linux设备驱动中的阻塞和非阻塞I/O

[基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到条件满足. 2.非阻塞 非阻塞操作是指在进行设备操作是,若操作条件不满足并不会挂起,而是直接返回或重新查询(一直占用CPU资源)直到操作条件满足为止. 当用户空间的应用程序调用read(),write()等方法时,若设备的资源不能被获取,而用户又希望以阻塞的方式来访问设备,驱动程序应当在设备驱动层的

Linux设备驱动开发 - 平台设备驱动

Linux2.6的内核中引入了一种新的设备驱动模型-平台(platform)设备驱动,平台设备驱动分为平台设备(platform_device)和平台驱动(platform_driver),平台设备的引入使得Linux设备驱动更加便于移植. 一.平台设备平台设备结构体: 1 struct platform_device { 2 const char * name; /* 设备名 */ 3 int id; 4 struct device dev; /* 设备结构体 */ 5 u32 num_res

linux设备驱动第三篇:写一个简单的字符设备驱动

在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存. 下面就开始学习如何写一个简单的字符设备驱动.首先我们来分解一下字符设备驱动都有那些结构或者方法组成,也就是说实现一个可以使用的字符设备驱动我们必须做些什么工作. 1.主设备号和次设备号 对于字符设备的访问是通过文件系统中的设备名称进行的.他们通常位于/dev目录下.如下: [plain] vie

Linux设备驱动开发学习(1):前言

虽然网络上已经有很多Linux设备驱动开发学习的文章和博客,更是有很多经典的Linux设备驱动开 发的书籍,写这些博文似乎意义不大,但把自己的学习过程.学习心得记录下来,一方面有着强化巩固的 意义,另一方面也是把所学知识转化为自己所得的必要途径之一,这是我写这些的博客的原始动力.

linux设备驱动中的并发控制

并发指的是多个执行单元同时.并行被执行,而并发的执行单元对共享资源的访问则很容易导致竞态 linux内核中主要竞态1.多对称处理器的多个CPU  2.单CPU内进程与抢占它的进程 3.中断(硬中断.软中断.Tasklet.下半部)与进程之间访问共享内存资源的代码区称为“临界区”,临界区需要被以某种互斥机制加以保护,中断屏蔽.原子操作.自旋锁和信号量等是linux设备驱动中可采用的互斥途径. 这几个互斥的介绍: 1.中断屏蔽,这个主要用于单CPU,中断屏蔽将使得中断和进程之间的并发不再发生.使用方

深入浅出~Linux设备驱动中的阻塞和非阻塞I/O

今天意外收到一个消息,真是惊呆我了,博客轩给我发了信息,说是俺的博客文章有特色可以出本书,,这简直让我受宠若惊,俺只是个大三的技术宅,写的博客也是自己所学的一些见解和在网上看到我一些博文以及帖子里综合起来写的,,总之这又给了额外的动力,让自己继续前进,,希望和大家能够分享一些自己的经验,,在最需要奋斗的年级以及在技术的领域踽踽独行的过程中有共同的伙伴继续前进~ 今天写的是Linux设备驱动中的阻塞和非阻塞I/0,何谓阻塞与非阻塞I/O?简单来说就是对I/O操作的两种不同的方式,驱动程序可以灵活的