linux内存管理初学

虚拟内存模型

Linux 内核本身并不运行在虚拟空间中,其使用的是物理寻址模式。

物理内存被分割为界面,一个内存页面的大小由PAGE_SIZE宏决定。

虚拟地址空间的方式使程序员可以将巨大的结构用于连续的地址,而不必考虑物理内存上的限制。

线性地址到物理地址

线性地址需要由处理器或者一个单独的MMU转换为物理地址,转换方式如下:

解析的方式为:

1.用线性地址中的第一个位段为下标可以在页面目录中找的一个表项,这个表项指向某个中间目录。

2.用线性地址中的第二个位段为下标可以在该中间目录中找到一个表项,该表项指向某个页面表。

3.用线性地址中的第三个位段为下标可以在该页面表中找到一个表项,该表项指向物理内存中的某个物理页面。

4.用线性地址中的第四个位段为偏移量,将次偏移量与该物理页面的基地址相加便得到相应的物理地址。

注 : TLB中存的是页面目录基地址。

而内核空间的线性地址解析成物理地址的过程相对简单,因为系统本身要为自己维护一张页表是一件很恶心的事情,所以内核空间的地址和物理地址是简单的直接映射,0xc0000000就是两者的偏移量。

也就是说:对于系统空间,给定一个虚地址x,其物理地址是x中减去PAGE_OFFSET;相应的,给定一个物理地址x,其虚地址是x+PAGE_OFFSET。

当然,不能全部用来做简单映射,因为如果内存有4G,那么如果直接全部做简单映射,那么内核只能访问0-1G的内存了,所以内核中实际是前896M做直接映射,剩下的用来做vmalloc申请区,永久内存映射区,固定映射区等。如下图:

几个创建进程函数

Fork:子进程只是复制父进程的资源,两进程内存空间独立,运行时并行。为了降低运行时的开销,对资源采用写时复制(也就是fork并不直接拷贝资源,只是当发生写入的时候才完成拷贝)。

Vfork:共享地址空间,创建后进程父进程阻塞直到子进程结束。

Clone:有参数,可以有选择的将数据复制给子进程,剩下的通过指针共享。

几个申请内存的函数的区别

1. kmalloc和vmalloc分配内核空间的内存,malloc分配用户空间的内存。

2. kmalloc物理连续,vmalloc虚拟地址连续。

3. kmalloc能分配的空间大小有限,vmalloc和malloc能分配的较大。

4. 内存在被DMA时需要物理连续。

5. Kmalloc更快

6. Kmalloc使用slab机制,返回地址之后就已经对应实际内存了。

缺页中断

如果MMU处理器不能访问一个页面,它将产生一个缺页中断。Linux缺页异常程序必须能区分由编程引起的以及由引用属于地址空间还未分配物理页框的页引起的异常,如果合法则分配新的页框。

每个进程都有自己的页表。

页面管理

请求换页

为了节省内存,操作系统只会加载那些正在被执行程序使用的虚拟页面。比如,某个数据库程序可能要对某个数据库进行查询操作,此时并不是数据库的所有内容都要加载到内存中去,而只加载那些要用的部分。这种仅将要访问的界面载入的技术叫请求换页。

当进程试图访问不在内存中的虚拟地址时,将触发一个缺页中断。

如果出错的地址是无效的,比如进行了一个随机的写操作,则操作系统终止此进程,此进程的出错不会影响其他进程。

如果出错的地址是有效的,但是它访问的页面不在内存中。则操作系统必须将此界面从磁盘映像中读出来。访盘时间比较长,进程必须等待一段时间直到页面被取出来。取过来的页面放在一个空闲的物理页框之中,同时此进程的页表中将添加对应此虚拟页面框号的入口。然后进程从出错的地方从新开始运行。

交换

如果进程需要把一个虚拟页面调入物理内存而正好系统没有空闲的物理页面,操作系统必须丢弃系统中某些页面来为之腾出空间。

如果那些从物理内存中丢弃出来的界面来自于磁盘上的可执行文件或者数据文件,并且没有修改过则不需要保存那些界面。当进程再次需要此页面时,直接从可执行文件或者数据文件中读出即可。

但是如果页面被修改过,则系统必须将其保存以备再次访问。这种界面叫做dirty界面。当从内存中移出来的时候,他们必须保存在叫做交换文件的特殊文件中。相对于cpu和内存的速度,访问交换文件的速度很慢,所以操作系统必须衡量好将那些dirty页交换或将其保留在内存中做出一个选择。

如果丢弃页面的算法选择的不够好,则可能不断地出现页面被写入又被从磁盘中读回的情况使效率变低。Linux使用最近最少使用(LRU)页面衰老算法来公平的选择将要从系统中抛弃的页面。这种算法为每个页面设置一个年龄,它随页面访问次数而变化。页面被访问的次数越多则越年轻,相反则衰老。

Linux高速缓冲

缓冲区高速缓冲(buffer cache)

缓冲区高速缓冲包含了由块设备使用的数据缓冲区。这些缓冲区包含了从设备中读取的数据块或写入设备的数据块。如果数据能够在缓冲区高速缓冲中找到,则系统没有必要在物理块设备上进行实际的读操作。

页面高速缓冲(page cache)

页面高速缓冲是页面I/O操作访问数据所使用的磁盘高速缓存。我们在文件系统会看到,read(),write()和mmap()系统调用对常规文件的访问都是通过页面高速缓存来完成的。

缓冲区高速缓存和页面高速缓存的区别:缓冲区高速缓存是块设备的cache,页面高速缓冲是用来做文件系统的cache,也就是它直接记忆我们打开的文件(例如使用两次man命令,可以明显感觉第二次更快)。

交换高速缓冲(swap cache)

就是交换空间在内存中的缓存。当写入交换空间的文件并没有被再次修改,那么下次再丢弃他的时候就不需要再次写入交换空间,这个就是通过swap cache来做的。

注意:

使用top命令会发现有buffer和cache的概念:

Buffer:简单的说是要被写入磁盘的,磁盘和主存的速度不一,所以需要缓冲区做一个中间层,写入数据的话先写入缓冲区,这样的话写入的进程没有必要陷入等待。

Cache(非CPU和主存件的cache):简单的说就是从磁盘读入的,存储在cache里以备后面再次使用。经常被用在磁盘I/O请求上,如一个文件被访问,则其将被放入cache中,以备以后再有进程访问。

Cache和buffer都是需要占用内存的。

原文:

A buffer is something that has yet to be "written" to disk. A cache is something that has been "read" from the disk and stored for later use.

来自为知笔记(Wiz)

时间: 2024-08-05 06:41:01

linux内存管理初学的相关文章

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Linux内存管理机制

一.首先大概了解一下计算机CPU.Cache.内存.硬盘之间的关系及区别. 1.  CPU也称为中央处理器(CPU,Central Processing Unit)是一块超大规模的集成电路, 是一台计算机的运算核心(Core)和控制核心( Control Unit).它的功能主要是解释计算机指令以及处理计算机软件中的数据.中央处理器主要由三核心部件组成,运算器.控制器和总线(BUS),运算器又主要由算术逻辑单元(ALU)和寄存器(RS)组成. 2.Cache即高速缓冲存储器,是位于CPU与主内存

Linux内存管理 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4491368.html Linux内存管理 摘要:本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法.力求从外到内.水到渠成地引导网友分析Linux的内存管理与使用.在本章最后,我们给出一个内存映射的实例,帮助网友们理解内核内存管理与用户内存管理之间的关系,希望大家最终能驾驭Linux内存管理. 前言 内存管理一向是所有操作系统书

linux内存管理浅析

[地址映射](图:左中)linux内核使用页式内存管理,应用程序给出的内存地址是虚拟地址,它需要经过若干级页表一级一级的变换,才变成真正的物理地址.想一下,地址映射还是一件很恐怖的事情.当访问一个由虚拟地址表示的内存空间时,需要先经过若干次的内存访问,得到每一级页表中用于转换的页表项(页表是存放在内存里面的),才能完成映射.也就是说,要实现一次内存访问,实际上内存被访问了N+1次(N=页表级数),并且还需要做N次加法运算.所以,地址映射必须要有硬件支持,mmu(内存管理单元)就是这个硬件.并且需

启动期间的内存管理之初始化过程概述----Linux内存管理(九)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检测到可用内存和寄存器. 而我们今天要讲的boot阶段就是系统初始化阶段使用的内存分配器. 1 前景回顾 1.1

linux内存管理---物理地址、线性地址、虚拟地址、逻辑地址之间的转换

linux内存管理---虚拟地址.逻辑地址.线性地址.物理地址的区别(一) 这篇文章中介绍了四个名词的概念,下面针对四个地址的转换进行分析 CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步(如下图): 首先,将给定一个逻辑地址(其实是段内偏移量,这个一定要理解!!!),CPU要利用其段式内存管理单元,先将为个逻辑地址转换成一个线程地址, 其次,再利用其页式内存管理单元,转换为最终物理地址. 这样做两次转换,的确是非常麻烦而且没有必要的,因为直接可以把线性地址抽像给进程.之所以这样冗余

Linux内存管理 (一) 内存组织

内存管理是内核最复杂同时也是最重要的一部.其特点在于非常需要处理器和内核之间的协作. 首先内存划分为结点,在内核中表示为pg_data_t,每个结点划分为内存域. 以下的所有数据结构或代码都做了不同程度的精减,一方面是为了保留相关代码,除去细枝末叶,另一方面是为了美观. 结点的数据结构为 <mmzone.h>typedef struct pglist_data { struct zone node_zones[MAX_NR_ZONES]; /*内存结点所包含的内存域数组*/ struct zo

Linux内存管理1

1.前言 关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识的整理. 本文将主要以X86架构来介绍Linux内存管理的相关知识. 2. 内存寻址 内存寻址是操作系统设计的硬件基础之一 操作系统是横跨软件和硬件的桥梁 操作系统设计者必须在硬件相关代码和硬件无关代码之间划分清晰的界限,以便操作系统很容易的移植到不同的平台 内存寻址的不同时期 (1)石器时代---8位寻址:4004是4位寻址,8080是8位寻址,由一个主累加器(寄存器A)和6个次累加器(寄存器B,C,D,E,H和L),没有段

Python学习第六天----Linux内存管理、进程管理、RPM包安装管理及源码安装软件

Linux内存管理.进程管理.RPM包安装管理及源码安装软件 一.交换分区     交换分区其实就相当于Windows系统下的虚拟内存的概念,当物理内存不够用的时候,由操作系统将硬盘的一块区域划分出来作为内存使用.具体使用方法如下:      [[email protected] ~]# fdisk -l 磁盘 /dev/sdb:16.1 GB, 16106127360 字节,31457280 个扇区 Units = 扇区 of 1 * 512 = 512 bytes 扇区大小(逻辑/物理):5