1 linux内存管理
地址类型
物理地址
出现在cpu地址总线上的寻址物理内存的地址信号,是地址变换的最终结果
线性地址(虚拟地址)
在32位cpu架构下,可以表示4g的地址空间,用16进制表示就是
0x00000000到0xffffffff
逻辑地址
程序代码编译后,出现在汇编程序中的地址
地址转换
cpu将一个逻辑地址转换为物理地址:
利用段式内存管理单元,将逻辑地址转换成线性地址
再利用页式内存管理单元,将线性地址转换成物理地址
段式管理
(16位cpu)
有20位的地址线,1m的内存空间,由于寄存器只有16位,只能访问65536
个存储单元,64k
因此cpu采用了内存分段的管理模式,cpu内部加入了段寄存器,把1M的
空间分为若干个逻辑段,要求如下:
逻辑段的起始地址必须是16的倍数(最后四个二进制位必须为0)
逻辑段的最大容量最大为64k
物理地址的形成方式:
段地址是16的倍数,形式为xxxx0h,即前16位是变化的,可以只保存前
16位二进制位来保存整个段基地址,所以使用时需要用段寄存器左移补
4个0来得到实际的段地址
确定内存单元在存储器中的具体位置: 段地址+偏移量
逻辑地址=段基地址+段内偏移量
物理地址=段寄存器值*16+逻辑地址
16位cpu有四个段寄存器,程序可同时访问四个不同含义的段
cs+ip 用于代码段的访问
cs 存放程序的段基址 用这两个寄存器就可以得到一个内存物理地址
ip 指向下条要执行的指令在cs段的偏移量
ss+sp 用于堆栈段的访问 直接访问栈顶单元的内存地址
ss 指向堆栈段的基地址
sp 指向栈顶
ds+bx 用于数据段的访问
ds 值左移四位得到数据段的起始地址
bx 偏移量
es+bx 用于附加段的访问
es 值左移四位得到附加段起始地址
bx 偏移量
(32位cpu)
有两种不同的工作方式:
实模式 与16位cpu一致
保护模式 段基地址长达32位 段寄存器存放的是一个地址
(段选择器), 选择器从内存中得到一个32位的段地址
页式管理
线性地址分为固定长度的组,称为页
linux中所有段的基地址均为0,所以线性地址=逻辑地址
linux页式管理
linux2.3.29内核采用了四级页管理架构
页全局目录
页上级目录
页中间目录
页表
2 linux进程地址空间
linux采用虚拟内存管理技术,每个进程都有独立的进程地址空间,约3G
linux将4G的虚拟地址空间划分为
用户空间 从0到0xbfffffff 随进程切换发生变化
内核空间 从3G到4G
用户进程只能访问用户空间,可以通过系统调用访问内核空间
查看线性地址
px aux
cat /proc/<pid>/maps
内核内存分配
应用程序中 malloc
linux内核中 kmalloc
函数原型:
#include<linux/slab.h>
void *kmalloc(size_t size,int flags)
size 要分配的内存大小
flags 分配标志,控制kmalloc的行为
GFP_AUTOMIC 在进程上下文之外的代码(包括中断处理)中分配内存,不睡眠
GFP_KERNEL 进程上下文中的分配,可能睡眠(16M-896M)
__GFP_DMA 分配能够DMA的内存区(物理地址在16m以下的页帧)
__GFP_HIGHMEM 分配的内存位于高端内存(896以上)
按页分配
get_zeroed_page(unsigned int flags)//返回指向新页面的指针,页面清零
__get_free_page(unsigned int flags)//同上,但不清零
__get_free_pages(unsigned int flags,unsigned int order)
//分配若干个连续的页面,返回指向该内存区域的指什,不清零
释放内存
void free_page(unsigned long addr)
void free_pages(unsigned long addr,unsigned long order)
3 linux内核地址空间
内核空间是由内核负责映射,不会随进程改变发生变化
物理内存为896M以上的为高端内 存
内核空间分布:
(3G开始)
直接映射区(direct memory region) 896M
8M
动态映射区(vmalloc region)
8k
KMAP区4M
固定映射区4M
4k
(4G结束)
-----------------------------------------
直接映射区 从3G开始,最大896M的线性地址区间
线性地址=3G+物理地址
动态映射区 地址由内核函数vmalloc来进行划分,线线空间连续,物理空间不
一定
永久内存映射区(PKMap region)对于896m以上的高端内存
访问方法:
1 alloc_page(__GFP_HIGHMEM)分配高端内存页
2 kmap函数将分配到的高端内存映射到该区域
固定映射区(fixing mapping region)
4 linux内核链表
链表的数据结构: 数据域和指针域
定义如下:
sturct list_head{
struct list_head *next,*prev;
};
内核链表为双向循环链表
链表的操作主要有:
/*初始化链表头*/
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*插入节点*/
/**
* 节点前插入
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head
*head)
{
__list_add(new, head, head->next);
}
/**
*节点尾插入
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct
list_head *head)
{
__list_add(new, head->prev, head);
}
/*删除节点*/
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the
entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/*提取数据结构*/
/**
* list_entry - get the struct for this entry
* @ptr:the &struct list_head pointer.
* @type:the type of the struct this is embedded in.
* @member:the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/* 遍历 */
/**
* list_for_each-iterate over a list
* @pos:the &struct list_head to use as a loop cursor.
* @head:the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
5 linux内核定时器
度量时间差
时钟中断 由系统的定时硬件以周期性的时间间隔产生,这个间隔由内核跟据hz来
确定,hz与体系结构无关,可配置(50-1200),x86平台默认为1000
时钟中断发生后,全局变量jiffies(unsigned long)会加1,驱动程序常
利用其来计算不同事件的时间间隔
内核定时器 (双向链表)
用于控制某个函数(定时器处理函数)在未来的某个特定时间执行(只执行一次)
struct timer_list{
struct list_head entry //内核使用
unsigned long expires //超时的jiffies的值
void (*function)(unsigned long) 超时处理函数
unsigned long data //超时处理函数参数
struct tvec_base *base //内核使用
};
/*初始化定时器队列*/
void init_timer(struct timer_list *timer);
/*启动定时器*/
void add_timer(struct timer_list *timer);
/*定时器超时前将其删除*/
void del_timer(struct timer_list *timer);
示例代码如下:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <asm/uaccass.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Retacn Yue");
MODULE_DESCRIPTION("timer module");
MODULE_ALIAS("timer module");
sturct timer_list timer;
void timer_function(int para){
prink("timer expired and para is %d\n",para);
}
int timer_init(){
/*初始化定时器*/
init_timer(&timer);
timer.data=5; /*超时处理函数参数*/
timer.expires=jiffies+(20*HZ); /*超时jiffies的值*/
timer.function=timer_function; /*超时处理函数*/
/*启动定时器*/
add_timer(&timer);
return 0;
}
void timer_exit(){
del_timer(&timer);
}
module_init(timer_init);
module_exit(timer_exit);
- 浏览: 249102 次
- 性别:
- 来自: 济南
文章分类
- 全部博客 (303)
- c (31)
- c++ (16)
- java (18)
- c# (1)
- python (3)
- java web (6)
- oracle (7)
- sqlserver (2)
- mysql (2)
- android (24)
- android系统 (15)
- android多媒体部分 (15)
- android游戏 (12)
- linux (26)
- javaScript (1)
- ajax (1)
- node JS (2)
- html (5)
- apache (3)
- jboss (1)
- weblogic (0)
- 通信协议 (10)
- 云计算 (1)
- 分布式 (5)
- ejb (1)
- webservice (5)
- 设计模式 (16)
- JNI (6)
- swing (13)
- 版本控制 (1)
- UML (1)
- xml (4)
- spring (5)
- hibernate (5)
- struts1 (3)
- struts2 (4)
- ibatis (0)
- tomcat (2)
- 心得体会 (1)
- css (1)
- 嵌入式 (41)
- arm体系结构 (10)
发表评论
-
u-boot Makefile 文件分析
2013-06-01 21:44 2366Makefile文件分析 # #(C)Copyri ... -
uboot start.S文件分析
2013-06-03 22:18 1285U-boot第一个开始文件arch\arm\cpu\arm1 ... -
u-boot mkconfig文件分析
2013-05-31 21:29 1107Mkconfig文件分析 #!/bin/ ... -
链接地址学习笔记
2013-05-05 12:40 1238链接地址 启动过程 示例代码如下: ... -
DDR学习笔记
2013-05-11 14:19 999DDR 15条地址线32k 128M*2(20)=2(2 ... -
nand flash学习笔记一
2013-05-13 21:05 930Nandflash 原理图上有data0-data7 ... -
openJTAG学习笔记一
2013-05-22 21:45 2130安装软件 光盘Windows\install目录下的 01.O ... -
linux进程管理学习笔记
2013-03-28 20:57 1295linux 进程管理 1 linux进程控制 进程的四个要素: ... -
字符设备驱动程序学习笔记一
2013-04-01 21:55 827linux 驱动程序 字符设备驱动程序 网络接口驱动程序 块设 ... -
字符设备驱动程序学习笔记二
2013-04-04 10:29 713字符驱动程序 1 设备号 字符设备通过字符设备文件来存取 ls ... -
字符设备驱动程序学习笔记三
2013-04-04 14:03 728memdev.h文件示例代码如下: #ifndef _MEM ... -
字符设备驱动程序学习笔记四
2013-04-05 11:12 555竟争与互斥 程序调试 1 ... -
GPIO学习笔记
2013-04-14 19:50 770用汇编点亮一个led 1看原理图GPK4=0,led亮G ... -
系统时钟学习笔记
2013-05-04 21:59 80112m晶振----->pll------>cpu ... -
UART学习笔记
2013-05-04 22:00 1097串口(UART) DIV_VAL=(PCLK/(bpsx1 ... -
嵌入式linux系统学习笔记
2013-03-06 21:39 895嵌入式linux内核制作 1 清除原有配置文件与中间文件 x8 ... -
原理图学习笔记一
2013-02-17 22:24 368画个草图也挺过瘾 -
进程间通信学习笔记一(管道通信)
2013-02-01 20:08 1361进程间通信(ipc) 应用场景: 数据传输 资源共享 通知事件 ... -
进程间通信学习笔记二(信号通信)
2013-02-16 21:39 730信号通信 用户按某些键时,产生信号 硬件异常产生信号 进程用k ... -
进程间通信学习笔记三(共享内存通信)
2013-02-16 21:40 577共享内存通信 被多个进程共享的一部分物理内存,是进程间共享数据 ...
相关推荐
深入理解LINUX内存管理学习笔记
《深入理解LINUX内存管理》学习笔记a.PDF
个人多年学习并总结的有关Linux内存管理的笔记,希望对Linux内核爱好者有所帮助!
《深入理解LINUX内存管理》学习笔记c.PDF
《深入理解LINUX内存管理》学习笔记b.PDF
《深入理解linux内存管理》学习笔记 Linux 高阶学习
《深入理解LINUX内存管理》学习笔记,亲生体会,详细记录
Linux 操作系统 内存管理笔记,总结的非常不错。对学习Linux内核很有帮助。
应大家要求上传。可嵌入到工程上的C语言实现的内存泄漏检查代码!!!!!...深入理解LINUX内存管理学习笔记。常见的内存错误。以及缓冲区缓冲区溢出攻击:原理,防御及检测,并给出全部代码以及ppt
它涵盖了多个方面,包括文件操作、进程管理、内存管理、网络编程等。 Linux系统编程涵盖了众多领域,从基础的文件操作到高级的网络通信和多线程编程,为开发者提供了广泛的功能和灵活性。在这个领域工作的开发者需要...
系统内存管理 内核通过硬盘上称为交换空间(swap space)的存储区域来实现虚拟内存。内核在交换空间和实际的物理内存之间反复交换虚拟内存中的内容。这使得系统以为自己拥有比物理内存更多的可用内存。 内存被划分为...
主要内容包括多任务,调度和进程管理,物理内存的管理以及内核与相关硬件的交互,用户空间的进程如何访问虚拟内存,如何编写设备驱动程序,模块机制以及虚拟文件系统,Ext文件系统属性和访问控制表的
这是本人集合了一些ARM linux学习资料,包含了《ARM体系结构与编程-杜春雷》,linux物理内存管理,linux下的连接脚本基础,嵌入式linux系统开发技术等一些相关资料,希望对爱好者有用!
Linux-uboot-学习笔记(8):uboot启动内核 uboot启动时,在执行到theKernel指针时即跳转到内核执行,也就标志着uboot的结束。在此之前uboot要进行内核启动的最后准备:从内核镜像的部署位置将内核搬移到DDR中,校验...
Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。
全书分为20章,内容包括进程管理、进程间通信、内存管理、文件系统、I/O接口及资源管理、内核的编译及调试原理、网络通信、内核安全、USB驱动程序等。 对于想了解Linux开发,以及从事Linux内核编程的开发人员来说,...