引用文章

  • Linux阅马场
  • 初探Linux内核态——通过proc文件系统作快速问题定位
  • linux通过meminfo 与 slab 定位内存泄漏
  • 曾文斌: /proc/meminfo之谜完全揭秘
  • vmalloc与mmap
  • FREE命令显示的BUFFERS与CACHED的区别
  • Linux ate my ram
  • mm_struct简介
  • 详细讲解从用户空间申请内存到内核如何为其分配内存的过程
  • Linux进程地址管理之mm_struct
  • Linux Memory Mapping--mmap kernel 2.6
  • 郭健: Linux内存模型——平坦、非连续与稀疏
  • 郝健: Linux内存管理学习笔记
  • 郝健: Linux内存管理学习笔记-第1课
  • 第二课
  • 第三课
  • 第四课
  • 第五课
  • 第六课
  • 陈延伟:任督二脉之内存管理总结笔记
  • 宋宝华:Linux内核的连续内存分配器(CMA)——避免预留大块内存
  • 宋宝华: Linux mmap的多种情况和背后的差异
  • 避免物理内存碎片化
  • 宋宝华:Linux的任督二脉——进程调度和内存管理
  • 宋宝华: CPU是如何访问到内存的?--MMU最基本原理
  • 宋牧春: Linux内核slab内存的越界检查——SLUB_DEBUG
  • 宋牧春: 多图详解Linux内存分配器slub
  • 多核心Linux内核路径优化的不二法门之-slab与伙伴系统
  • 宋宝华: 关于DMA ZONE和dma alloc coherent若干误解的彻底澄清
  • 又是一年三月三:Linux的任督二脉之内存管理直播
  • linux 内存管理初探
  • 进程内存管理初探
  • 宋宝华:网上坑爹的Linux资料汇总之内存管理
  • 宋宝华: Linux为什么一定要copy_from_user ?
  • 宋宝华:swappiness=0究竟意味着什么?
  • 为什么手工drop_caches之后cache值并未减少?

一. 用户进程内存管理

1.1 进程的虚拟地址空间VMA

1.2 进程的pmap

1.3 VMA与程序的各个段以及库关系

1.4 VSS, RSS, PSS, USS的关系

1.5 page fault的几种可能性

1.6 进程内存泄漏的界定

1.7 内存泄漏的检查

二. 内核内存管理

2.1 内存分布

2.2 内存管理图

三. 用户空间和内核空间内存分配关系

3.1 内存总体关系图

3.2 Libc, Slab与buddy

3.3 kmalloc VS vmalloc/ioremap

四. 一个mmap的小实验

4.1 kernel driver

#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <asm/io.h>
#include <linux/device.h>/* length of the two memory areas */
#define NPAGES 16struct mmap_dev_info_st {/* char device */dev_t mmap_dev;struct cdev mmap_cdev;struct class *mmap_class;/* pointer to the vmalloc'd area - alway page aligned */int *vmalloc_area;/* pointer to the kmalloc'd area, rounded up to a page boundary */int *kmalloc_area;/* original pointer for kmalloc'd area as returned by kmalloc */void *kmalloc_ptr;
};static struct mmap_dev_info_st mmap_dev_info;static int mmap_open(struct inode *inode, struct file *filp)
{return 0;
}static int mmap_release(struct inode *inode, struct file *filp)
{return 0;
}/* mmap's the kmalloc'd area which is physically contiguous */
int mmap_kmem(struct file *filp, struct vm_area_struct *vma)
{int ret = 0;long length = vma->vm_end - vma->vm_start;int *kmalloc_area = mmap_dev_info.kmalloc_area;printk(KERN_ERR "%s: start\n", __func__);/* check length - do not allow larger mappings than the number ofpages allocated */if (length > NPAGES * PAGE_SIZE) {ret = -EIO;printk(KERN_ERR "%s: length err.\n", __func__);goto err;}/* map the whole physically contiguous area in one piece */ret = remap_pfn_range(vma, vma->vm_start,virt_to_phys((void *)kmalloc_area) >> PAGE_SHIFT,length, vma->vm_page_prot);if (ret < 0) {printk(KERN_ERR "%s: ret:%d err.\n", __func__, ret);goto err;}return 0;err:return ret;
}/* mmap's the vmalloc'd area which is not physically contiguous */
int mmap_vmem(struct file *filp, struct vm_area_struct *vma)
{int ret = 0;long length = vma->vm_end - vma->vm_start;unsigned long start = vma->vm_start;char *vmalloc_area_ptr = (char *)mmap_dev_info.vmalloc_area;unsigned long pfn = 0;printk(KERN_ERR "%s: start\n", __func__);/* check length - do not allow larger mappings than the number ofpages allocated */if (length > NPAGES * PAGE_SIZE) {ret = -EIO;printk(KERN_ERR "%s: length err.\n", __func__);goto err;}/* loop over all pages, map it page individually */while (length > 0) {pfn = vmalloc_to_pfn(vmalloc_area_ptr);ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED);if (ret < 0) {printk(KERN_ERR "%s: remap_pfn_range err.\n", __func__);goto err;}start += PAGE_SIZE;vmalloc_area_ptr += PAGE_SIZE;length -= PAGE_SIZE;}return 0;err:return ret;
}/* character device mmap method */
static int mmap_mmap(struct file *filp, struct vm_area_struct *vma)
{int ret = 0;if (vma->vm_pgoff == 0) {/* at offset 0 we map the vmalloc'd area */ret =  mmap_vmem(filp, vma);  } else if (vma->vm_pgoff == NPAGES) {/* at offset NPAGES we map the kmalloc'd area */ret = mmap_kmem(filp, vma);} else {/* at any other offset we return an error */ret = -EIO;}return ret;
}static struct file_operations mmap_fops = {.open = mmap_open,.release = mmap_release,.mmap = mmap_mmap,.owner = THIS_MODULE,
};static int __init my_mmap_init(void)
{int ret = 0;int i = 0;printk(KERN_ERR "%s: start\n", __func__);/* allocate a memory area with kmalloc. Will be rounded up to a page boundary */if ((mmap_dev_info.kmalloc_ptr = kmalloc((NPAGES + 2) * PAGE_SIZE, GFP_KERNEL)) == NULL) {ret = -ENOMEM;goto out;}/* round it up to the page bondary,即找到页对齐的地址 */mmap_dev_info.kmalloc_area = (int *)PAGE_ALIGN((unsigned long)mmap_dev_info.kmalloc_ptr);/* allocate a memory area with vmalloc. */if ((mmap_dev_info.vmalloc_area = (int *)vmalloc(NPAGES * PAGE_SIZE)) == NULL) {ret = -ENOMEM;goto out_kfree;}/* get the major number of the character device */if ((ret = alloc_chrdev_region(&mmap_dev_info.mmap_dev, 0, 1, "mmap")) < 0) {printk(KERN_ERR "could not allocate major number for mmap\n");goto out_vfree;}/* initialize the device structure and register the device with the kernel */cdev_init(&mmap_dev_info.mmap_cdev, &mmap_fops);if ((ret = cdev_add(&mmap_dev_info.mmap_cdev, mmap_dev_info.mmap_dev, 1)) < 0) {printk(KERN_ERR "could not allocate chrdev for mmap\n");goto out_unalloc_region;}/* mark the pages reserved,即让申请的memory不被交换到磁盘。*/for (i = 0; i < NPAGES * PAGE_SIZE; i += PAGE_SIZE) {//mark_page_reserved(vmalloc_to_page((void *)(((unsigned long)(mmap_dev_info.vmalloc_area)) + i)));//mark_page_reserved(virt_to_page(((unsigned long)(mmap_dev_info.kmalloc_area)) + i));SetPageReserved(vmalloc_to_page((void *)(((unsigned long)(mmap_dev_info.vmalloc_area)) + i)));SetPageReserved(virt_to_page(((unsigned long)(mmap_dev_info.kmalloc_area)) + i));}/* store a pattern in the memory - the test application will check for it */for (i = 0; i < (NPAGES * PAGE_SIZE / sizeof(int)); i += 2) {mmap_dev_info.vmalloc_area[i] = (0xaffe << 16) + i;mmap_dev_info.vmalloc_area[i + 1] = (0xbeef << 16) + i;mmap_dev_info.kmalloc_area[i] = (0xdead << 16) + i;mmap_dev_info.kmalloc_area[i + 1] = (0xbeef << 16) + i;}/* create class */mmap_dev_info.mmap_class = class_create(THIS_MODULE, "mmap_class");if (IS_ERR(mmap_dev_info.mmap_class)) {printk(KERN_ERR "class_create failed.\n");ret = -1;goto out_unalloc_region;}/* create device */device_create(mmap_dev_info.mmap_class, NULL, mmap_dev_info.mmap_dev, NULL, "mmap_dev");printk(KERN_ERR "%s: end\n", __func__);return ret;out_unalloc_region:unregister_chrdev_region(mmap_dev_info.mmap_dev, 1);out_vfree:vfree(mmap_dev_info.vmalloc_area);mmap_dev_info.vmalloc_area = NULL;out_kfree:kfree(mmap_dev_info.kmalloc_ptr);mmap_dev_info.kmalloc_ptr = NULL;out:return ret;
}static void __exit my_mmap_exit(void)
{int i = 0;/* unregister device */device_destroy(mmap_dev_info.mmap_class, mmap_dev_info.mmap_dev);/* remove the character deivce */cdev_del(&(mmap_dev_info.mmap_cdev));class_destroy(mmap_dev_info.mmap_class);unregister_chrdev_region(mmap_dev_info.mmap_dev, 1);/* unreserve the pages */for (i = 0; i < NPAGES * PAGE_SIZE; i += PAGE_SIZE) {//free_reserved_page(vmalloc_to_page((void *)(((unsigned long)(mmap_dev_info.vmalloc_area)) + i)));//free_reserved_page(virt_to_page(((unsigned long)(mmap_dev_info.kmalloc_area)) + i));ClearPageReserved(vmalloc_to_page((void *)(((unsigned long)(mmap_dev_info.vmalloc_area)) + i)));ClearPageReserved(virt_to_page(((unsigned long)(mmap_dev_info.kmalloc_area)) + i));}/* free the memory areas */if (mmap_dev_info.vmalloc_area) {vfree(mmap_dev_info.vmalloc_area);mmap_dev_info.vmalloc_area = NULL;}if (mmap_dev_info.kmalloc_ptr) {kfree(mmap_dev_info.kmalloc_ptr);mmap_dev_info.kmalloc_ptr = NULL;}
}module_init(my_mmap_init);
module_exit(my_mmap_exit);MODULE_DESCRIPTION("mmap demo driver");
MODULE_AUTHOR("vector");
MODULE_LICENSE("GPL");
ifneq ($(KERNELRELEASE),)                                                                                                                                                                               obj-m := map_driver.o
elsePWD  := $(shell pwd)
KDIR := /lib/modules/$(shell uname -r)/buildall:$(MAKE) -C $(KDIR) M=$(PWD) modulesclean:rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions modules.order Module.symvers
endif

4.2 userspace test app

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>#define LEN (16*4096)int main(int argc, void **argv)
{int i = 0;int fd;unsigned int *vadr;fd = open("/dev/mmap_dev", O_RDWR);if (fd < 0) {perror("open");return -1;}vadr = mmap(0, LEN, PROT_READ, MAP_SHARED, fd, 0);if (vadr == MAP_FAILED) {perror("mmap");return -1;}printf("------------------------------------------------");for (i = 0; i < (LEN / 4); i++) {printf("0x%08x,", *(vadr + i));if ((i % 10) == 0)printf("\n");}close(fd);return(0);
}

4.3 测试结果

Linux - 内存管理相关推荐

  1. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  2. 万字长文,别再说你不懂Linux内存管理了(合辑),30 张图给你安排的明明白白...

    之前写了两篇详细分析 Linux 内存管理的文章,读者好评如潮.但由于是分开两篇来写,而这两篇内容其实是有很强关联的,有读者反馈没有看到另一篇读起来不够不连贯,为方便阅读这次特意把两篇整合在一起,看这 ...

  3. 别再说你不懂Linux内存管理了,10张图给你安排的明明白白!

    来自:后端技术学堂 过去的一周有点魔幻,有印象的有三个新闻:天猫总裁绯闻事件,蘑菇街裁员,不可能打工的周某也放出来了.三件事,两件和互联网行业相关,好像外面的世界很是精彩啊!吃瓜归吃瓜,学习还是不能落 ...

  4. Linux内存管理原理【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3695517.html 本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址 ...

  5. Linux内存管理【转】

    转自:http://www.cnblogs.com/wuchanming/p/4360264.html 转载:http://www.kerneltravel.net/journal/v/mem.htm ...

  6. Linux内存管理之高端内存映射

    一:引子 我们在前面分析过,在linux内存管理中,内核使用3G->4G的地址空间,总共1G的大小.而且有一部份用来做非连续空间的物理映射(vmalloc).除掉这部份空间之外,只留下896M大 ...

  7. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  8. Linux内存管理 (2)页表的映射过程

    专题:Linux内存管理专题 关键词:swapper_pd_dir.ARM PGD/PTE.Linux PGD/PTE.pgd_offset_k. Linux下的页表映射分为两种,一是Linux自身的 ...

  9. Linux内存管理 (4)分配物理页面

    专题:Linux内存管理专题 关键词:分配掩码.伙伴系统.水位(watermark).空闲伙伴块合并. 我们知道Linux内存管理是以页为单位进行的,对内存的管理是通过伙伴系统进行. 从Linux内存 ...

  10. Linux 交换内存空间原理(swap)(Linux内存管理)(cgroups)

    文章目录 什么是swap? 为什么需要swap? swap的缺点? 到底要不要swap? 内存不够用 内存勉强够用 内存充裕 桌面环境 服务器环境 swap大小配置多少比较合适? 怎么配置swap? ...

最新文章

  1. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Select模型
  2. 光伏行业需理性看待低价中标 市场竞争是必然选择
  3. MySQL主从配置的一些总结
  4. pythonGB2312乱码问题
  5. Dubbo服务暴露原理
  6. python输出键值列表_Python 键值分组或分区数据
  7. ffmpeg中av_strlcpy替换了pstrcpy
  8. 命令行验证apk签名
  9. solr java 全量,Solr实时创建增量或全量索引
  10. 38张技术知识图谱,IT架构师必备【附下载】
  11. 实用软件工程(吕云翔版)——第一章
  12. 【无人机】基于卡尔曼滤波实现无人机捷联惯导算法与组合导航附matlab代码
  13. java api 8 中文_java8 JDK1.8 API 中文 翻译版 java帮助文档
  14. VM15虚拟机下载及安装教程
  15. 您的滴滴2020年度出行报告,请查收!
  16. Gunicorn+django部署
  17. 【jenkins】创建一个project基础配置、自动化邮件发送、pytest_terminal_summary收集结果
  18. 关于怎么给Date类型的数据加上一天的时间
  19. 美国在线计算机硕士项目,美国计算机硕士项目申请难度
  20. 我的程序员之路:11 年高考结束到 17 年日本修士的心路历程

热门文章

  1. 智慧城市八大应用,助力城市更加智慧
  2. [小故事大道理] -- 木桶原理的逆向思考
  3. 数学实验课MATLAB实验报告二(题目+代码)
  4. 移动共享开发(二)各平台SSO(免登录)配置 微信和微信朋友圈、QQ、QQ空间、新浪微博、腾讯微博、人人
  5. 【2017年总结】-花开半夏
  6. 【大学篇】大学的意义
  7. Mysql中使用select into语句给变量赋值没有匹配记录时的结果
  8. java程序员平时都使用哪些软件??
  9. 2012成都网络赛赛后【缺CHJ】
  10. 音视频技术开发周刊 | 229