`

linux内存管理学习笔记

阅读更多



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);

分享到:
评论

相关推荐

    深入理解LINUX内存管理学习笔记

    我不可能完全理解LINUX内存管理的精髓,肯定有很多地方理解错误。希望大 家能够指正,以便提高,谢谢。 学习方法: 可能您第一次阅读的时候很多地方都不理解,不用担心。那您可能需要阅读一些 文件系统的知识。 或者...

    《深入理解LINUX内存管理》学习笔记a.PDF

    《深入理解LINUX内存管理》学习笔记a.PDF

    Linux内存管理笔记

    Linux内存管理笔记详细介绍了Linux操作系统内核中内存管理机制的关键知识点,下面将依次对这些知识点进行详细说明: 存储器的层次结构:计算机系统采用分层的存储子系统以在存储容量、访问速度、成本效益之间取得...

    《深入理解LINUX内存管理》学习笔记c.PDF

    《深入理解LINUX内存管理》学习笔记c.PDF

    《深入理解LINUX内存管理》学习笔记b.PDF

    《深入理解LINUX内存管理》学习笔记b.PDF

    《深入理解linux内存管理》学习笔记 Linux 高阶学习

    在《深入理解Linux内存管理》的学习笔记中,我们将会探讨以下几个关键概念: 1. **内存区域(Memory Regions)**:Linux将内存划分为不同的区域,如保留区(Reserved)、初始化数据区(Initialized Data)、未初始...

    linux内存和缓冲区完美教程大全

    最后,"**深入理解LINUX内存管理学习笔记**"这份文档将带你深入了解Linux内核的内存管理机制,包括物理内存、虚拟内存、页面分配和回收、交换机制等。理解这些概念有助于优化你的程序性能,特别是在处理大量数据或高...

    linux-memory-manage.rar_Linux 内存管理_linux_memory_内存管理 linux_内存管理

    Linux内存在操作系统中扮演着至关重要的角色,它...提供的“内存管理.ppt”可能包含更详细的讲解和实例,而“www.pudn.com.txt”可能是相关资料链接或笔记,进一步深入学习这些内容,将有助于掌握Linux内存管理的精髓。

    linux学习笔记,linux命令整理

    在Linux操作系统的学习中,掌握命令行的使用是至关重要的。...总的来说,Linux学习笔记是一个全面了解和掌握Linux系统操作的基础教程,涵盖了从基本命令到高级管理的诸多方面,对提升Linux技能有很大帮助。

    linux 内存管理系列

    本系列涵盖了"深入理解Linux内存管理"、"Linux虚拟内存"以及相关的读书笔记,为那些希望深入了解Linux内存机制的读者提供了宝贵的资料。下面将详细阐述这些主题的主要知识点。 首先,我们来探讨"深入理解Linux内存...

    linux课堂学习笔记

    Linux内核提供了进程管理、内存管理、文件系统、网络协议栈等核心功能,同时支持多种硬件平台,包括我们接下来要讨论的ARM架构。 ARM(Advanced RISC Machines)是一种微处理器架构,以其低功耗和高性能在嵌入式...

    linux嵌入式学习笔记更新中

    Linux 嵌入式学习笔记主要涵盖了Linux操作系统的基础知识以及C语言编程的相关内容。下面将对这些知识点进行详细的解析。 1. Linux基础操作: - 登录:在Linux系统中,用户通过`用户名:密码`的方式登录系统。 - ...

    韩顺平linux学习笔记

    韩顺平 Linux 学习笔记 本学习笔记涵盖了 Linux 的基础知识、Samba 服务的搭建、Web 项目的开发和发布等内容。学习笔记分为多个阶段,从基础的 Linux 平台开发到高级的 Unix 环境编程,并涉及到 Linux 应用系统开发...

    linux学习笔记分享 (Linux入门绝佳)

    Linux 学习笔记分享 (Linux 入门绝佳) Linux 是一个开源的操作系统,它的目录架构是非常重要的概念。在 Linux 中,目录架构是按照 FHS(Filesystem Hierarchy Standard)标准来组织的。下面是 Linux 中一些重要的...

    linux0.11 内核学习笔记

    这份“Linux0.11 内核学习笔记”详细解读了这个早期内核的结构、工作原理以及相关的编程技术。下面,我们将深入探讨其中的关键知识点。 一、内核架构 Linux 0.11内核采用单内核设计,所有的系统服务都集中在一个可...

    linux驱动学习笔记

    Linux驱动学习笔记主要涵盖的是与Linux操作系统内核交互的程序设计,这在系统开发和设备管理中至关重要。Linux驱动程序是连接硬件设备和操作系统之间的桥梁,使得操作系统能够控制和利用硬件资源。以下是对这些文件...

Global site tag (gtag.js) - Google Analytics