内核采用 struct page 来表示一个物理页,在其中记载了诸多物理页的属性,比如 物理页被几个线程使用(如若没有则表示该页可以释放),页对应的虚拟地址。

  首先需要知道的是,分配物理页可以分为两个步骤 :

    1) 寻找内核中空闲 处于3-4G 4K对齐的虚拟地址。

        i)虚拟页是否空闲 由页表项的属性决定,里面会有标志位记录。

        ii)虚拟页需要4K对齐是强制性的,因为页目录项的低12 bit是用来记录页目录属性的,高20 bit才是记录页目录项的物理地址。

    2) 寻找内核中空闲的物理页。

    3) 通过改变页表项来修改映射关系,如何修改的请看 我的另一篇博客 : https://www.cnblogs.com/vizdl/p/11925205.html

 // 物理页表示
struct page {
unsigned 1ong flags ;
atomic_t _count ;
atomic_t mapcount;
unsigned 1ong private;
struct address_space * mapping;
pgoff_t index;
struct list_ head lru;
void *virtual;
}; 

  由物理地址进行分区 : 在系列文章2中也讲了分区的一些缘由,详情可看系列博客2中内核空间分区部分 https://www.cnblogs.com/vizdl/p/12233623.html

  内核空间一般被分为三个区 : ZONE_DMA, ZONE_NORMAL, ZONE_HIGHMEM,直接提供的接口可以建议内核从特定区域申请物理页。

struct zone
{
unsigned long
watermark[NR_ WMARK];
unsigned 1ong lowmem_ reserve[MAX_ NR_ ZONES];
struct per_cpu_pageset pageset[NR_CPUS];
spinlock_t lock;
struct free_ area
free_area[MAX_ ORDER] spinlock_t
lru_1ock;
struct zone_1ru
{
struct list_head list;
unsigned 1ong nr_saved_scan;
} lru[NR_ LRU_ LISTS];
struct zone_reclaim_ stat reclaim_ stat;
unsigned long pages_scanned;
unsigned long flags;
atomic_1ong_t vm_stat[NR_ _VM_ ZONE STAT_ ITEMS];
int prev_priority;
unsigned int inactive_ratio;
wait_queue_head_t *wait_ table;
unsigned 1ong wait_ table_ hash_ nr_ entries;
unsigned 1ong wait_ table_ bits;
struct pglist_ data *zone_ pgdat;
unsigned long zone_ start_ pfn;
unsigned long spanned_ pages;
unsigned 1ong present_ pages;
const char *name;
};

  对物理页操作接口: 物理页采用buddy算法来进行分配,单位最小为1页。只能申请2^order页,这也是buddy算法的特性。

  特别说明 :

  1) gfp_t gfp_mask,这个参数就是用来建议内核在具体哪个区域得到物理页。

  2) 如若已经无可用物理页了,就会采用一系列 页面置换算法, 将物理页上的内容保存到磁盘中的swap sapce(交换空间)中去。

// 分配 2^order个连续的物理页(使用buddy);
struct page *al1oc_ pages(gfp_t gfp_mask, unsigned int order);
// 利用page中的 virtual属性 得到对应的虚拟地址。
void *page_address(struct page *page);
// 分配 2^order个连续的物理页,且直接返回逻辑地址
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
// 分配一页物理内存
struct page *alloc_page(gfp_t pfp_mask);
// 分配一页物理内存 并返回逻辑地址
struct page *__get_free_page(gfp_t pfp_mask);
// 获取填充为0的页
unsigned long get_zeroed_page(unsigned int gfp_mask);

  物理页的释放函数 :

// 释放物理地址
void __free_pages(struct page *page, uns igned int order);
void free_pages(unsigned long addr, unsigned int order);
void free_page(unsigned 1ong addr);

  

  对于小块内存分配,内核也提供了Slab分配器来进行分配,这个分配器可以提供一个缓冲,不会将申请的物理解除绑定虚拟地址,理由是一些小块的内存(特别是结构体)会在内核中频繁地申请与释放。

  Slab层的一些接口 :

// 字节为单位的内存分配(slab层)
// kmalloc()在<linux/slab.h>中声明:
// 分配物理地址连续的地址, 出错返回NULL
void *kmalloc(size_t size, gfp_t flags);
// 物理不一定连续,虚拟连续。
void *vmalloc(unsigned long size);
// 释放
void kfree(const void *ptr);
void vfree(const void *addr);

  slab层的好处 :

    1) 避免了频繁地寻找空闲虚拟页和空闲物理页,提高效率。

    2) 避免了因频繁修改物理页与虚拟页映射关系而导致的物理页无法有大块平坦(连续)物理空间。

  slab本质其实就是一个内存池。 而内存池之后我可能会总结malloc的内存分配算法,那个算法完全可以用于slab。不过一个是堆内存池,一个是内核内存池。

  slab与Buddy的关系:

  

  由上述 : 目前对于内核空间的内存分配已经有一个简单的策略认识了, 即 小块内存 用slab分配器分配,大块内存(最小单位为页)用 Buddy系统 直接分配。而slab层内存池的内存也是Buddy分配出来的。只不过Slab在此做了一个缓冲罢了。

Linux内存管理解析(三) : 内核对内核空间的内存管理的更多相关文章

  1. linux(centOS7)的基本操作(三) 用户、组、权限管理

    用户和组 1.用户.组.家目录的概念 linux系统支持多用户,除了管理员,其他用户一般不应该使用root,而是应该向管理员申请一个账号.组类似于角色,系统可以通过组对有共性的用户进行统一管理.每个用 ...

  2. Android内存优化(三)避免可控的内存泄漏

    相关文章 Android性能优化系列 Java虚拟机系列 前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已.因此,如何避免.发现和解决 ...

  3. Linux内核入门到放弃-内存管理-《深入Linux内核架构》笔记

    概述 内存管理的实现涵盖了许多领域: 内存中的物理内存页管理 分配大块内存的伙伴系统 分配较小内存块的slab.slub和slob分配器 分配非连续内存块的vmalloc机制 进程的地址空间 在IA- ...

  4. (转)Linux环境进程间通信系列(五):共享内存

    原文地址:http://www.cppblog.com/mydriverc/articles/29741.html 共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A ...

  5. Java中OutOfMemoryError(内存溢出)的三种情况及解决办法

    转载自:http://blog.sina.com.cn/s/blog_701c951f0100n1sp.html 相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题, ...

  6. jvm内存溢出的三种情况以及解决办法

    1       前言相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深 ...

  7. Android内存优化(三)详解内存分析工具MAT

    前言 在这个系列的前四篇文章中,我分别介绍了DVM.ART.内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT. 1.概述 在进行内存分析时,我们可以使用M ...

  8. Linux内核设计笔记12——内存管理

    内存管理学习笔记 页 页是内核管理内存的基本单位,内存管理单元(MMU,管理内存并把虚拟地址转化为物理地址的硬件)通常以页为单位进行处理,从虚拟内存的角度看,页就是最小单位. struct page{ ...

  9. 解析Linux内核的基本的模块管理与时间管理操作---超时处理【转】

    转自:http://www.jb51.net/article/79960.htm 这篇文章主要介绍了Linux内核的基本的模块管理与时间管理操作,包括模块加载卸载函数的使用和定时器的用法等知识,需要的 ...

随机推荐

  1. Codeforces Round #615 (Div. 3) 题解

    A - Collecting Coins 题意: 给你四个数a,b,c,d,n.问你是否能将n拆成三个数A,B,C,使得A+a=B+b=C+c. 思路: 先计算三个数的差值的绝对值abs,如果abs大 ...

  2. 【WPF学习】第十七章 键盘输入

    当用户按下键盘上的一个键时,就会发生一系列事件.下表根据他们的发生顺序列出了这些事件: 表 所有元素的键盘事件(按顺序) 键盘处理永远不会像上面看到的这么简单.一些控件可能会挂起这些事件中的某些事件, ...

  3. applyColorMap 在OpenCV中对灰度图进行颜色映射,实现数据的色彩化

    什么是色彩映射: 说直白点就是将各种数据映射成颜色信息,例如:温度,高度,压力,密度,湿度,城市拥堵数据等等 色彩化后更加直观表达 在OpenCV里可以使用 Mat im_gray = imread( ...

  4. RocketMQ消息模型

    rocketmq采用的是发布-订阅的模式,不需要每个消费者维护自己的消息队列,生产者将消息发送到topic,消费者订阅此topic 读取消息. 基本概念: 消息模型:消息模型包括producer,co ...

  5. requestAnimationFrame 与 seeTimeout 的区别

    requestAnimationFrame 随着浏览器的刷新而执行. let a =  () =>{          doSomething() ;         window.reques ...

  6. 安卓开发实战-记账本APP(三)

    本次实现的是有关登录,注册和整体页面的改观,实现下方选项导致页面的切换效果. 利用到的技术有Sqlite数据库的增删改查,与fragment实现.由于暂时没有找到合适的图标,先借用微信的图标暂代一下. ...

  7. 《快乐编程大本营》java语言训练班 3课:java的运算符

    第1节. 算术运算符 第2节. 递增和递减运算符 第3节. 比较运算符 第4节. 逻辑运算符 第5节. 运算符优先级 第6节. 字符串运算 http://code6g.com/pxphp/px/ban ...

  8. PAT_B1002数字分类

    #include<stdio.h> #include<iostream> using namespace std; int main(){ ,a2=,a3=,a5=; ; ; ...

  9. 机器学习(ML)七之模型选择、欠拟合和过拟合

    训练误差和泛化误差 需要区分训练误差(training error)和泛化误差(generalization error).前者指模型在训练数据集上表现出的误差,后者指模型在任意一个测试数据样本上表现 ...

  10. jsp作用域问题

    jsp的四大作用域,还是要注意一下,刚才练习javabean输入时间,第一次有个地方写错了,之后改过来之后,刷新tomcat,但是时间一直不变,很奇怪, 最后发现<useBean>标签里面 ...