linux驱动开发--内核空间中内存的申请与释放

1、Linux内存管理

linux内存最小管理单位为页(page),通常一页为4kb。
linux系统中,在初始化时,内核为每个物理内存页建立一个page的管理结构,操作物理内存时实际上就是操作page页。

物理地址:出现在cpu地址总线上的寻址物理内存的地址信号,是地址变换的最终结果。
线性地址(虚拟地址):在32位cpu架构上,可以表示4G的地址空间,也就是0x00000000-0xFFFFFFFF。
逻辑地址:实际上是一个相对地址,是程序代码经过编译之后在汇编程序中出现的地址。

linux内核地址转换:出现在机器语言指令(程序编译后得到的二进制机器码序列)中的内存地址都是逻辑地址,逻辑地址必须被转换为线性地址,MMU将线性地址转换成物理地址,最终实现对应物理内存的访问。在linux系统中,逻辑地址和线性地址(虚拟地址)是一致的。

2、实例代码

/**
*Copyright (c) 2013.TianYuan
*All rights reserved.
*
*文件名称: kernelspace.c
*文件标识: 内核空间中内存的申请与释放
*
*当前版本:1.0
*作者:wuyq
*
*取代版本:xxx
*原作者:xxx
*完成日期:2013-11-18
*/
#include <linux/init.h>
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>

MODULE_LICENSE("GPL");
#define	PAGE_NUM	4/*编码幻数*/

unsigned char *kernelkmalloc = NULL;
unsigned char *kernelpagemem = NULL;
unsigned char *kernelvmalloc = NULL;

static int __init kernelspace_init(void)
{
	int ret = -ENOMEM;
	/*
	*GFP_KERNEL:分配内存,分配过程中可能导致睡眠。
	*GFP_ATOMIC:分配过程中不会导致睡眠。
	*GFP_DMA:申请到的内存通常情况下,位于0~16M之间
	*__GFP_HIGNMEM:申请高端内存(物理地址896M以上的)
	*/
	kernelkmalloc = (unsigned char *)kmalloc(100, GFP_KERNEL);
	if(IS_ERR(kernelkmalloc)){
		printk("kmalloc failed!\n");
		ret = PTR_ERR(kernelkmalloc);
		goto failure_kmalloc;
	}
	printk("kmalloc space :0x%lx!\n",(unsigned long)kernelkmalloc);

	kernelpagemem = (unsigned char *)__get_free_pages(GFP_KERNEL, PAGE_NUM);/*请求或释放的页数的2的幂*/
	if(IS_ERR(kernelpagemem)){
		printk("get_free_pages failed!\n");
		ret = PTR_ERR(kernelpagemem);
		goto failure_get_free_pages;
	}
	printk("get_free_pages address:0x%lx\n",(unsigned long)kernelpagemem);

	kernelvmalloc = (unsigned char *)vmalloc(1024*1024);
	if(IS_ERR(kernelvmalloc)){
		printk("vmalloc failed!\n");
		ret = PTR_ERR(kernelvmalloc);
		goto failure_vmalloc;
	}
	printk("vmalloc address: 0x%lx\n",(unsigned long)kernelvmalloc);
	return 0;
failure_vmalloc:
	free_pages((unsigned long)kernelpagemem, PAGE_NUM);
failure_get_free_pages:
	kfree(kernelkmalloc);
failure_kmalloc:
	return ret;
}

static void __exit kernelspace_exit(void)
{
	vfree(kernelvmalloc);
	free_pages((unsigned long)kernelpagemem, PAGE_NUM);
	kfree(kernelkmalloc);
}

module_init(kernelspace_init);
module_exit(kernelspace_exit);

KERNELDIR ?=/root/Desktop/work/ldd3/linux-2.6.31_TX2440A
PWD := $(shell pwd)
obj-m += kernelspace.o

default:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	@rm -f *.o *.ord* *.sy* *.mod.* *.ko
时间: 2024-10-02 05:45:34

linux驱动开发--内核空间中内存的申请与释放的相关文章

Linux驱动开发常用调试工具---之内存读写工具devmem和devkmem

问题 这段时间实验室要完成一个内存故障注入工具和寄存器故障注入工具,在编写驱动的过程中,调试起来很麻烦(一般都是printk打印出来的,调试起来太不方便),于是想 "可不可以在调试设备驱动的时候,利用一个小工具来读写内存某块区域的值以及CPU中寄存器的值? 这点前辈的大神已经为我们找到了,参见<LDD3>的<第十五章 内存映射和DMA> 目前已经有这样的工具了devmem和devkmem,就是通过mmap映射/dev/mem的. 这个工具的源码简单,google一下到处都

linux驱动开发--内核链表

1.内核链表定义 在<linux/list.h>中定义 struct list_head{ struct list_head *next, *prev; }; 在list_head结构中包含两个指向list_head结构的指针next和prev,在实际使用中,它通常被组织成双向循环链表. 内核链表结构体不包含数据域,只包含维护链表的指针域. 内核链表被包含在其他数据结构体中使用. 初始化链表头INIT_LIST_HEAD函数void INIT_LIST_HEAD(struct list_hea

linux驱动开发--内核定时器

1.内核定时器 时钟中断:由系统的定时硬件以周期性的时间间隔发生,这个间隔(也就是频率)由内核根据常数HZ来确定. HZ常数:她是一个与体系结构无关的常数,可以配置50-1200之间,可以在内核中配置 tick:她是HZ的倒数,也就是每发生一次硬件定时器中断的事件间隔.如HZ为200,tick为5毫秒. jiffies核心变数:它是linux核心变数(32位变数,unsigned long),它被用记录自开机以来,已经过多少个tick.每发生一次硬件定时器中断,jiffies变数会被加1. 定时

Linux驱动开发必看详解神秘内核(完全转载)

Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入Linux设备驱动程序的神秘世界之前,让我们从驱动程序开发人员的角度看几个内核构成要素,熟悉一些基本的内核概念.我们将学习内核定时器.同步机制以及内存分配方法.不过,我们还是得从头开始这次探索之旅.因此,本章要先浏览一下内核发出的启动信息,然后再逐个讲解一些有意思的点. 2.1 启动过程 图2-1显示

《Android深度探索(卷1):HAL与驱动开发》——1.5节如何学习Linux驱动开发

1.5 如何学习Linux驱动开发 Android深度探索(卷1):HAL与驱动开发 由于Linux的内核版本更新较快(稳定版本1至3月更新一次,升级版本1至2周更新一次),每一次内核的变化就意味着Linux驱动的变化(就算不需要修改驱动代码,至少也得在新的Linux内核版本下重新编译),所以Linux内核的不断变化对从事Linux驱动开发的程序员影响比较大.不过这对于学习Linux驱动开发来说影响相对较小.因为不管是哪个版本的Linux内核,开发Linux驱动的方法和步骤基本相同,只要掌握了一

红帽-台式机x64 架构linux 驱动开发的安装问题

问题描述 台式机x64 架构linux 驱动开发的安装问题 我们知道Linux下的驱动开发可以静态加载也可以动态加载的.本人想在台式机上面的小红帽 下静态安装驱动.每次动态加载太费事了,但是貌似没有嵌入式Linux 下面的简单.有哪些方法可以实现系统自动加载,难道只有修改启动脚本么? 请大牛不吝赐教!跪拜!三客优! 解决方案 自己编译一个系统内核吧,这样想怎么弄就怎么弄了 或者查阅红帽的开发手册,看看有木有说明 解决方案二: 谢谢,网上可以下载到红帽的内核么 台式机上面怎么放系统里面启动呢? 解

linux驱动开发--copy_to_user 、copy_from_user函数实现内核空间数据与用户空间数据的相互访问

设备读操作 如果该操作为空,将使得read系统调用返回负EINVAL失败,正常返回实际读取的字节数 ssize_t (*read)(struct file *filp, char __user *buf, size_t  count, lofft *f_pos);filp:待操作的设备文件file结构体指针buf:待写入所读取数据的用户空间缓冲区指针count:待读取数据字节数f_pos:待读取数据文件位置,读取完成后根据实际读取字节数重新定位返回:成功实际读取的字节数,失败返回负值 设备写操作

linux驱动开发--字符设备:添加文件指针偏移的功能

设备移位操作llseek 对应lseek系统调用的设备移位操作为llseek 默认情况为允许设备移位操作 大部分字符设备提供的都是数据流而不是一个数据区,比如串口,对于这些设备而言移位操作毫无意义 设备可选择是否支持移位操作 支持设备移位操作loff_t (*llseek)(struct file *filp, loff_t off, int whence);filp:待操作的设备文件file结构体指针off:待操作的定位偏移值(可正可负)whence:待操作的定位起始位置返回:返回移位后的新文

linux驱动开发--内核模块参数

内核模块参数,验证小例子: /** *Copyright (c) 2013.TianYuan *All rights reserved. * *文件名称: Modparma.c *文件标识: 模块参数的验证 * *当前版本:1.0 *作者:wuyq * *取代版本:xxx *原作者:xxx *完成日期:2013-11-18 */ #include <linux/init.h> #include <linux/module.h> /*内核提供的机制:在用户空间修改内核模块中全局变量的