Linux嵌入式操作系统的内存详解
嵌入式linux操作系统原理与应用

嵌入式Linux操作系统是一种针对嵌入式设备设计和优化的Linux操作系统。
它在嵌入式系统中发挥着关键作用,为嵌入式设备提供了丰富的功能和灵活性。
以下是嵌入式Linux操作系统的原理和应用方面的概述:嵌入式Linux操作系统原理:内核:嵌入式Linux操作系统的核心是Linux内核,它提供了操作系统的基本功能,包括处理器管理、内存管理、设备驱动程序、文件系统和网络协议栈等。
裁剪:为了适应嵌入式设备的资源限制,嵌入式Linux操作系统通常经过裁剪和优化,只选择必要的功能和驱动程序,以减小内存占用和存储空间,并提高性能和响应速度。
交叉编译:由于嵌入式设备通常具有不同的硬件架构和处理器,所以嵌入式Linux操作系统需要通过交叉编译来生成适用于目标设备的可执行文件和库。
设备驱动:嵌入式Linux操作系统需要适配各种硬件设备,因此需要编写和集成相应的设备驱动程序,以使操作系统能够正确地与硬件进行通信和交互。
嵌入式Linux操作系统应用:嵌入式设备:嵌入式Linux操作系统广泛应用于各种嵌入式设备,如智能手机、平板电脑、家用电器、工业控制系统、车载设备等。
物联网(IoT):随着物联网的快速发展,嵌入式Linux操作系统被广泛应用于连接的嵌入式设备,用于数据采集、通信、远程控制和智能化管理。
嵌入式开发板:嵌入式Linux操作系统在开发板上提供了丰富的开发环境和工具链,用于嵌入式软件开发和调试。
自定义嵌入式系统:开发者可以基于嵌入式Linux操作系统构建自定义的嵌入式系统,根据特定需求进行定制和开发,实现各种功能和应用。
嵌入式Linux操作系统的原理和应用非常广泛,它为嵌入式设备提供了灵活性、可定制性和强大的功能支持,使得开发者能够构建高度定制化和功能丰富的嵌入式系统。
单片机和linux嵌入式操作系统区别

单片机和linux嵌入式操作系统区别随着嵌入式行业硬件平台的性能增强,项目需求和功能日益复杂,ARM公司推出的 CORTEX-M3,更是让以往做单片机的工程师在芯片和技术选型面临两难选择,本专题将从芯片价格、整个系统的硬件软件设计及维护的成本等各个方面给您提供一个参考,并从技术角度分析单片机和带操作系统的系统的软件开发的异同点。
● 1.单片机与ARM等新处理器的价格比较● 2.带操作系统与不带操作系统的软件开发的区别● 2.1.驱动开发的区别● 2.2.应用程序开发的区别1. 单片机与ARM等新处理器的价格比较表1自己不熟悉的芯片和技术,最后的成本也可能更高。
2. 带操作系统与不带操作系统的软件开发的区别用通俗的话来说,一个处理芯片不运行操作系统,我们就把它称为单片机,而单片机编程就是写裸板程序,这个程序直接在板子上运行;相对的,另一种程序就是基于操作系统的程序,说得简单点就是,这种程序可以通过统一的接口调用“别人写好的代码”,在“别人的基础上”更快更方便地实现自己的功能。
2.1. 驱动开发的区别驱动开发的区别我总结有两点:能否借用、是否通用。
2.1.1 能否借用基于操作系统的软件资源非常丰富,你要写一个Linux设备驱动时,首先在网上找找,如果有直接拿来用;其次是找到类似的,在它的基础上进行修改;如果实在没有,就要研究设备手册,从零写起。
而不带操作系统的驱动开发,一开始就要深入了解设备手册,从零开始为它构造运行环境,实现各种函数以供应用程序使用。
举个例子,要驱动一块LCD,在单片机上的做法是:①首先要了解LCD的规格,弄清楚怎么设置各个寄存器,比如设置LCD的时钟、分辨率、象素②划出一块内存给LCD使用③编写一个函数,实现在指定坐标描点。
比如根据x、y坐标在这块内存里找到这个象素对应的小区域,填入数据。
基于操作系统时,我们首先是找到类似的驱动,弄清楚驱动结构,找到要修改的地方进行修改。
下面是单片机操作LCD的代码:①初始化:void Tft_Lcd_Init(int type){/** 设置LCD控制器的控制寄存器LCDCON1~5* 1. LCDCON1:* 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]* 选择LCD类型: TFT LCD* 设置显示模式: 16BPP* 先禁止LCD信号输出* 2. LCDCON2/3/4:* 设置控制信号的时间参数* 设置分辨率,即行数及列数* 现在,可以根据公式计算出显示器的频率:* 当HCLK=100MHz时,* Rate =1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x* {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x * {2x(CLKVAL+1)/(HCLK)}]* = 60Hz* 3. LCDCON5:* 设置显示模式为16BPP时的数据格式: 5:6:5* 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD 的接口信号): 反转* 半字(2字节)交换使能*/LCDCON1 = (CLKVAL_TFT_320240<<8) | (LCDTYPE_TFT<<5) | \(BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);LCDCON2 = (VBPD_320240<<24) |(LINEVAL_TFT_320240<<14) | \(VFPD_320240<<6) |(VSPW_320240);LCDCON3 = (HBPD_320240<<19) | (HOZVAL_TFT_320240<<8) | (HFPD_320240);LCDCON4 = HSPW_320240;// LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \// (HWSWP<<1);LCDCON5 = (FORMAT8BPP_565<<11) |(HSYNC_INV<<9) | (VSYNC_INV<<8) | (VDEN_INV << 6) | \(HWSWP<<0);/** 设置LCD控制器的地址寄存器LCDSADDR1~3* 帧内存与视口(view point)完全吻合,* 图像数据格式如下:* |----PAGEWIDTH----|* y/x 0 1 2 239* 0 rgb rgb rgb ... rgb* 1 rgb rgb rgb ... rgb* 1. LCDSADDR1:* 设置LCDBANK、LCDBASEU* 2. LCDSADDR2:* 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]* 3. LCDSADDR3:* OFFSIZE等于0,PAGEWIDTH等于(240*2/2)*/LCDSADDR1 = ((LCDBUFFER>>22)<<21) |LOWER21BITS(LCDBUFFER>>1);LCDSADDR2 = LOWER21BITS((LCDBUFFER+ \(LINEVAL_TFT_320240+1 )*(HOZVAL_TFT_320240+1)*2)>>1);LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_320240*2/2);/* 禁止临时调色板寄存器 */TPAL = 0;fb_base_addr = LCDBUFFER;bpp = 16;xsize = 320;ysize = 240;}②描点:/** 画点* 输入参数:* x、y : 象素坐标* color: 颜色值* 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),* 需要转换为5:6:5格式* 对于8BPP: color为调色板中的索引值,* 其颜色取决于调色板中的数值*/void PutPixel(UINT32 x, UINT32 y, UINT32 color){UINT8 red,green,blue;switch (bpp){case 16:{UINT16 *addr = (UINT16*)fb_base_addr + (y * xsize + x);red = (color >> 19) & 0x1f;green = (color >> 10) & 0x3f;blue = (color >> 3) & 0x1f;color = (red << 11) | (green << 5) | blue; // 格式5:6:5*addr = (UINT16) color;break;}case 8:{UINT8 *addr = (UINT8 *)fb_base_addr + (y * xsize + x);*addr = (UINT8) color;break;}default:break;}}下面是在Linux的LCD驱动里修改的地方(arch\arm\mach-s3c2440\mach-smdk2440.c):/* 320x240 */static struct s3c2410fb_mach_info smdk2440_lcd_cfg__initdata = {.regs = {.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | \S3C2410_LCDCON1_TFT | \S3C2410_LCDCON1_CLKVAL(0x04),.lcdcon2 = S3C2410_LCDCON2_VBPD(1) | \S3C2410_LCDCON2_LINEVAL(239) | \ S3C2410_LCDCON2_VFPD(5) | \S3C2410_LCDCON2_VSPW(1),.lcdcon3 = S3C2410_LCDCON3_HBPD(36) | \S3C2410_LCDCON3_HOZVAL(319) | \S3C2410_LCDCON3_HFPD(19),.lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \S3C2410_LCDCON4_HSPW(5),.lcdcon5 = S3C2410_LCDCON5_FRM565 |S3C2410_LCDCON5_INVVLINE |S3C2410_LCDCON5_INVV |S3C2410_LCDCON5_INVVDEN |S3C2410_LCDCON5_PWREN |S3C2410_LCDCON5_HWSWP,},.gpccon = 0xaaaa56aa,.gpccon_mask = 0xffffffff,.gpcup = 0xffffffff,.gpcup_mask = 0xffffffff,.gpdcon = 0xaaaaaaaa,.gpdcon_mask = 0xffffffff,.gpdup = 0xffffffff,.gpdup_mask = 0xffffffff,.fixed_syncs = 1,.type = S3C2410_LCDCON1_TFT,.width = 320,.height = 240,.xres = {.min = 320,.max = 320,.defval = 320,},.yres = {.max = 240,.min = 240,.defval = 240,},.bpp = {.min = 16,.max = 16,.defval = 16,},};这并不表示代码Linux的驱动程序就比单片机的驱动程序好写,怎么在几万个文件中找到要修改的代码,这也是需要艰苦的学习的。
嵌入式Linux系统中的闪存存储技术

MT 驱动程序是在 Ln x 专门为嵌入式环境开发的新的一类驱动程序。相对于 D i u 常规块没备驱动程序, 使用 Mr) r 驱动程序的主要优点在于 Mq 1 D驱动程序是专门为基于 闪存的设备所没汁的,它们通常有更好的支持、更好的管理和基十扇区的擦除和读写操
MT D子系统的工作层次和 函数调用关系,并且以 A 9R 2 0开发板为平 台,实 T 1 M90
现 MT D技 术 的操 作使 用过程
关键词:MT 嵌入式系统 Ln x D i u
1 引言
嵌入式 Lnx系统以其开源性和广泛的技术支持获得广大开发者的青睐。在嵌入式 i u 系统的开发过程中, 系统和数据 的存储是一项基本工作, 基于 M Me r Tcn l y F D( mo e o g y h o Dv e ei ,内存技术设备) JF 2Ju ln ah i yt e i ,日 c 和 F S ( ma i F s F e s m V ro 2 志型闪存文件 o l g l lS e sn
作 的接 E。 l
嵌入式 Ln x系统下的 MT i u D驱动程序接 1被划分为两类模块 :用户模块和硬件模 7  ̄ 1 块 。如图 1 所示,用户模块提供从用户空问直接使用的接 几,实现原始字符访问、原
3 0
维普资讯
科技 论 文
始块访问、闪存转换层 (T , l h r si ae) 日志文件系统 ( S Ju l g F L F s a io Lyr 和 a T n tn J , omai F l n F eS s m)等;硬件模块提供对 闪存设备的物理访问 ,实现在闪存上读、擦除和写操 i y e l t 作的实际例程 ,该模块并不直接对硬件进行操作,而是通过上述的用户模块来访问。
linux操作系统的结构及详细说明

linux操作系统的结构及详细说明linux的操作系统的结构你了解多少呢?下面由店铺为大家整理了linux操作系统的结构及详细说明的相关知识,希望对大家有帮助!linux操作系统的结构及详细说明:一、 linux内核内核是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
Linux 内核由如下几部分组成:内存管理、进程管理、设备驱动程序、文件系统和网络管理等。
系统调用接口:SCI 层提供了某些机制执行从用户空间到内核的函数调用。
这个接口依赖于体系结构,甚至在相同的处理器家族内也是如此。
SCI 实际上是一个非常有用的函数调用多路复用和多路分解服务。
在 ./linux/kernel 中您可以找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的部分。
1. 内存管理对任何一台计算机而言,其内存以及其它资源都是有限的。
为了让有限的物理内存满足应用程序对内存的大需求量,Linux 采用了称为“虚拟内存”的内存管理方式。
Linux 将内存划分为容易处理的“内存页”(对于大部分体系结构来说都是 4KB)。
Linux 包括了管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。
不过内存管理要管理的可不止 4KB 缓冲区。
Linux 提供了对 4KB 缓冲区的抽象,例如 slab 分配器。
这种内存管理模式使用 4KB 缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。
这样就允许该模式根据系统需要来动态调整内存使用。
为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。
由于这个原因,页面可以移出内存并放入磁盘中。
这个过程称为交换,因为页面会被从内存交换到硬盘上。
内存管理的源代码可以在 ./linux/mm 中找到。
2 .进程管理进程实际是某特定应用程序的一个运行实体。
嵌入式linux系统的启动流程

嵌入式linux系统的启动流程
嵌入式Linux系统的启动流程一般包括以下几个步骤:
1.硬件初始化:首先会对硬件进行初始化,例如设置时钟、中
断控制等。
这一步骤通常是由硬件自身进行初始化,也受到系统的BIOS或Bootloader的控制。
2.Bootloader引导:接下来,系统会从存储介质(如闪存、SD
卡等)的Bootloader区域读取引导程序。
Bootloader是一段程序,可以从存储介质中加载内核镜像和根文件系统,它负责进行硬件初始化、进行引导选项的选择,以及加载内核到内存中。
3.Linux内核加载:Bootloader会将内核镜像从存储介质中加载到系统内存中。
内核镜像是包含操作系统核心的一个二进制文件,它由开发者编译并与设备硬件特定的驱动程序进行连接。
4.内核初始化:一旦内核被加载到内存中,系统会进入内核初
始化阶段。
在这个阶段,内核会初始化设备驱动程序、文件系统、网络协议栈等系统核心。
5.启动用户空间:在内核初始化完毕后,系统将启动第一个用
户空间进程(init进程)。
init进程会读取并解析配置文件(如
/etc/inittab)来决定如何启动其他系统服务和应用程序。
6.启动其他系统服务和应用程序:在用户空间启动后,init进
程会根据配置文件启动其他系统服务和应用程序。
这些服务和应用程序通常运行在用户空间,提供各种功能和服务。
以上是嵌入式Linux系统的基本启动流程,不同的嵌入式系统可能会有一些差异。
同时,一些特定的系统也可以添加其他的启动流程步骤,如初始化设备树、加载设备固件文件等。
嵌入式linux常见评估指标介绍

嵌入式linux常见评估指标介绍在嵌入式项目预研前期阶段,我们常常需要对某个平台进行资源和性能方面的评估,以下是最常见的一些评估指标:1、内存评估系统内存空间通过free、cat /proc/meminfo或者top,查看内存情况。
一般有这样一个经验公式:应用程序可用内存/系统物理内存>70%时,表示系统内存资源非常充足,不影响系统性能;20%<应用程序可用内存/系统物理内存<70%时,表示系统内存资源基本能满足应用需求,暂时不影响系统性能;应用程序可用内存/系统物理内存<20%时,表示系统内存资源紧缺,需要增加系统内存;$ freetotal used free shared buff/c ac heav ai lableMem: 123496 21512 75132 1132 26852 63416Swap: 0 0 0$ cat /proc/meminfoMemTotal: 123496 kB //所有可用的内存大小,物理内存减去预留位和内核使用。
系统从加电开始到引导完成,firmware/B IOS要预留一些内存,内核本身要占用一些内存,最后剩下可供内核支配的内存就是MemTotal。
这个值在系统运行期间一般是固定不变的,重启会改变。
MemFree: 75132 kB //表示系统尚未使用的内存。
MemAvailable: 63400 kB //真正的系统可用内存,系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以这部分可回收的内存加上MemFree才是系统可用的内存Buffe rs: 5644 kB //用来给块设备做缓存的内存,(文件系统的met ad ata、pages)Cached: 19040 kB //分配给文件缓冲区的内存,例如vi一个文件,就会将未保存的内容写到该缓冲区SwapCached: 0 kB //被高速缓冲存储用的交换空间(硬盘的swap)的大小Active: 20356 kB //经常使用的高速缓冲存储器页面文件大小Inactive: 12628 kB //不经常使用的高速缓冲存储器文件大小Active(anon): 9412 kB //活跃的匿名内存Inactive(anon): 20 kB //不活跃的匿名内存Active(file): 10944 kB //活跃的文件使用内存Inactive(file): 12608 kB //不活跃的文件使用内存Unevictable: 0 kB //不能被释放的内存页Mlocked: 0 kB //系统调用 mlockSwapTotal: 0 kB //交换空间总内存SwapFree: 0 kB //交换空间空闲内存Dirty: 0 kB //等待被写回到磁盘的Wri te back: 0 kB //正在被写回的AnonPages: 8300 kB //未映射页的内存/映射到用户空间的非文件页表大小Mapped: 11480 kB //映射文件内存Shmem: 1132 kB //已经被分配的共享内存KReclaimable: 2132 kB //内核内存,内存压力时内核尝试回收Slab: 8240 kB //内核数据结构缓存SReclaimable: 2132 kB //可收回slab内存SUnreclaim: 6108 kB //不可收回slab内存KernelStack: 568 kB //内核消耗的内存PageTables: 516 kB //管理内存分页的索引表的大小NFS_Unstable: 0 kB //不稳定页表的大小Bounce: 0 kB //在低端内存中分配一个临时buffer作为跳转,把位于高端内存的缓存数据复制到此处消耗的内存WritebackTmp: 0 kB //FUSE用于临时写回缓冲区的内存CommitLimit: 61748 kB //系统实际可分配内存Committed_AS: 58568 kB //系统当前已分配的内存VmallocTotal: 1048372 kB //预留的虚拟内存总量VmallocUsed: 1288 kB //已经被使用的虚拟内存VmallocChunk: 0 kB //可分配的最大的逻辑连续的虚拟内存Per cpu: 32 kB //percpu机制使用的内存2、磁盘评估获取磁盘空间$ df -hFilesystem Size Used Available Use% Mounted on /dev/root 6.0M 6.0M 0 100% /romtmpfs 60.3M 1.1M 59.2M 2% /tmp/dev/mtdblock6 23.8M 9.0M 14.8M 38% /overlay overlayfs:/overlay 23.8M 9.0M 14.8M 38% /tmpfs 512.0K 0 512.0K 0% /dev Filesystem:代表该文件系统时哪个分区,所以列出的是设备名称。
linux 内存和CPU 分析

Linux下内存使用率、CPU使用率、以及运行原理Linux下怎样查看机器配置啊?cpu/内存/硬盘dmesg显示开机信息。
kernel会将开机信息存储在ring buffer中。
您若是开机时来不及查看信息,可利用dmesg来查看。
开机信息亦保存在/var/log目录中,名称为dmesg的文件里dmesg|grep hd硬盘dmesg|grep cpucpudmesg|grep proc内存dmesg|grep redhat操作系统dmesg|more更多信息uname -a操作系统版本查看linux cpu和内存利用率在系统维护的过程中,随时可能有需要查看 CPU 使用率,并根据相应信息分析系统状况的需要。
在 CentOS 中,可以通过 top 命令来查看 CPU 使用状况。
运行 top 命令后,CPU 使用状态会以全屏的方式显示,并且会处在对话的模式-- 用基于 top 的命令,可以控制显示方式等等。
退出 top 的命令为 q (在 top 运行中敲 q 键一次)。
操作实例:在命令行中输入“top”即可启动 toptop 的全屏对话模式可分为3部分:系统信息栏、命令输入栏、进程列表栏。
第一部分 -- 最上部的系统信息栏:第一行(top):“00:11:04”为系统当前时刻;“3:35”为系统启动后到现在的运作时间;“2 users”为当前登录到系统的用户,更确切的说是登录到用户的终端数 -- 同一个用户同一时间对系统多个终端的连接将被视为多个用户连接到系统,这里的用户数也将表现为终端的数目;“load average”为当前系统负载的平均值,后面的三个值分别为1分钟前、5分钟前、15分钟前进程的平均数,一般的可以认为这个数值超过 CPU 数目时,CPU 将比较吃力的负载当前系统所包含的进程;第二行(Tasks):“59 total”为当前系统进程总数;“1 running”为当前运行中的进程数;“58 sleeping”为当前处于等待状态中的进程数;“0 stoped”为被停止的系统进程数;“0 zombie”为被复原的进程数;第三行(Cpus):分别表示了 CPU 当前的使用率;第四行(Mem):分别表示了内存总量、当前使用量、空闲内存量、以及缓冲使用中的内存量;第五行(Swap):表示类别同第四行(Mem),但此处反映着交换分区(Swap)的使用情况。
Linux内存管理分析与研究

Linux内存管理分析与研究随着计算机技术的不断发展,操作系统在计算机系统中扮演着越来越重要的角色。
作为开源操作系统领域的佼佼者,Linux被广泛用于各种应用场景,包括服务器、桌面、嵌入式系统等。
内存管理是操作系统核心功能之一,对于系统性能和稳定性具有重要影响。
本文将对Linux内存管理进行深入分析,并探讨其存在的问题与解决方案。
Linux内存管理采用分页和分段技术,将物理内存划分为大小不同的页框或段框,以便更有效地利用和管理内存资源。
Linux通过将内存分为内核空间和用户空间,实现了内存的隔离和保护,同时允许用户进程使用不同的内存空间。
Linux内存管理存在的一个主要问题是内存分配不均。
由于内存分配是基于页框或段框的,当某些进程需要更多内存时,操作系统会从空闲的内存页框中分配内存。
然而,在实际情况中,由于页框大小固定,当需要分配大量内存时,可能会造成内存分配不均的情况。
另一个问题是浪费空间。
Linux为了提高内存利用率,采用了一种称为内存分页的技术。
然而,在某些情况下,当进程不再需要使用内存时,操作系统并不会立即将内存页框回收,而是保留在内存中以备将来使用,这可能会导致内存空间的浪费。
针对内存分配不均的问题,可以采取交换技术。
交换技术是一种将进程使用的内存部分移至磁盘上,以腾出更多内存供其他进程使用的方法。
在Linux中,可以使用瑞士文件系统(Swiss File System,SFS)作为交换设备,将不常用的内存页框交换到磁盘上,以便在需要时重新加载。
为了解决内存浪费问题,可以优化内存分配算法。
Linux中使用的内存分配算法是基于伙伴系统的,该算法会跟踪每个内存块的空闲状态。
当需要分配内存时,伙伴系统会选择一个适当大小的空闲块,并将其划分为所需的内存大小。
为了避免内存浪费,可以采取以下措施:增加空闲内存块的大小,以便更好地适应大内存需求;引入动态内存分配机制,使操作系统能够在需要时分配和回收内存;定期清理不再使用的内存块,以便及时回收内存空间。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
linux 内存是后台开发人员,需要深入了解的计算机资源。
合理的使用内存,有助于提升机器的性能和稳定性。
本文主要介绍 linux 内存组织结构和页面布局,内存碎片产生原因和优化算法,linux 内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。
从内存的原理和结构,到内存的算法优化,再到使用场景,去探寻内存管理的机制和奥秘。
一、走进 linux 内存1、内存是什么?1)内存又称主存,是 CPU 能直接寻址的存储空间,由半导体器件制成2)内存的特点是存取速率快2、内存的作用1)暂时存放 cpu 的运算数据2)硬盘等外部存储器交换的数据3)保障 cpu 计算的稳定性和高性能二、 linux 内存地址空间1、linux 内存地址空间 Linux 内存管理全貌2、内存地址——用户态&内核态•用户态:Ring3 运行于用户态的代码则要受到处理器的诸多•内核态:Ring0 在处理器的存储保护中,核心态•用户态切换到内核态的 3 种方式:系统调用、异常、外设中断•区别:每个进程都有完全属于自己的,独立的,不被干扰的内存空间;用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用;内核态线程共享内核地址空间;3、内存地址——MMU 地址转换•MMU 是一种硬件电路,它包含两个部件,一个是分段部件,一个是分页部件•分段机制把一个逻辑地址转换为线性地址•分页机制把一个线性地址转换为物理地址4、内存地址——分段机制1) 段选择符•为了方便快速检索段选择符,处理器提供了6 个分段寄存器来缓存段选择符,它们是:cs,ss,ds,es,fs 和 gs•段的基地址(Base Address):在线性地址空间中段的起始地址•段的界限(Limit):在虚拟地址空间中,段内可以使用的最大偏移量2) 分段实现•逻辑地址的段寄存器中的值提供段描述符,然后从段描述符中得到段基址和段界限,然后加上逻辑地址的偏移量,就得到了线性地址5、内存地址——分页机制(32 位)•分页机制是在分段机制之后进行的,它进一步将线性地址转换为物理地址•10 位页目录,10 位页表项, 12 位页偏移地址•单页的大小为 4KB6、用户态地址空间•TEXT:代码段可执行代码、字符串字面值、只读变量•DATA:数据段,映射程序中已经初始化的全局变量•BSS 段:存放程序中未初始化的全局变量•HEAP:运行时的堆,在程序运行中使用 malloc 申请的内存区域•MMAP:共享库及匿名文件的映射区域•STACK:用户进程栈•7、内核态地址空间•直接映射区:线性空间中从 3G 开始最大 896M 的区间,为直接内存映射区•动态内存映射区:该区域由内核函数 vmalloc 来分配•永久内存映射区:该区域可访问高端内存•固定映射区:该区域和 4G 的顶端只有 4k 的隔离带,其每个地址项都服务于特定的用途,如:ACPI_BASE 等8、进程内存空间•用户进程通常情况只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址•内核空间是由内核负责映射,不会跟着进程变化;内核空间地址有自己对应的页表,用户进程各自有不同额页表三、 Linux 内存分配算法内存管理算法——对讨厌自己管理内存的人来说是天赐的礼物1、内存碎片1)基本原理•产生原因:内存分配较小,并且分配的这些小的内存生存周期又较长,反复申请后将产生内存碎片的出现•优点:提高分配速度,便于内存管理,防止内存泄露•缺点:大量的内存碎片会使系统缓慢,内存使用率低,浪费大2) 如何避免内存碎片•少用动态内存分配的函数(尽量使用栈空间)•分配内存和释放的内存尽量在同一个函数中•尽量一次性申请较大的内存,而不要反复申请小内存•尽可能申请大块的 2 的指数幂大小的内存空间•外部碎片避免——伙伴系统算法•内部碎片避免——slab 算法•自己进行内存管理工作,设计内存池2、伙伴系统算法——组织结构1)概念•为内核提供了一种用于分配一组连续的页而建立的一种高效的分配策略,并有效的解决了外碎片问题•分配的内存区是以页框为基本单位的2)外部碎片•外部碎片指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域3) 组织结构•把所有的空闲页分组为 11 个块链表,每个块链表分别包含大小为 1,2,4,8,16,32,64,128,256,512 和 1024 个连续页框的页块。
最大可以申请1024 个连续页,对应 4MB 大小的连续内存3、伙伴系统算法——申请和回收1)申请算法•申请 2^i 个页块存储空间,如果 2^i 对应的块链表有空闲页块,则分配给应用•如果没有空闲页块,则查找 2^(i 1) 对应的块链表是否有空闲页块,如果有,则分配 2^i 块链表节点给应用,另外 2^i 块链表节点插入到 2^i 对应的块链表中•如果 2^(i 1) 块链表中没有空闲页块,则重复步骤 2,直到找到有空闲页块的块链表•如果仍然没有,则返回内存分配失败2)回收算法•释放 2^i 个页块存储空间,查找 2^i 个页块对应的块链表,是否有与其物理地址是连续的页块,如果没有,则无需合并•如果有,则合并成 2^(i 1)的页块,以此类推,继续查找下一级块链接,直到不能合并为止3)条件•两个块具有相同的大小•它们的物理地址是连续的•页块大小相同4、如何分配 4M 以上内存?1)为何限制大块内存分配•分配的内存越大, 失败的可能性越大•大块内存使用场景少2)内核中获取 4M 以上大内存的方法•修改 MAX_ORDER, 重新编译内核•内核启动选型传递"mem="参数, 如"mem=80M,预留部分内存;然后通过•request_mem_region 和 ioremap_nocache 将预留的内存映射到模块中。
需要修改内核启动参数, 无需重新编译内核. 但这种方法不支持 x86 架构, 只支持ARM, PowerPC 等非 x86 架构•在 start_kernel 中 mem_init 函数之前调用 alloc_boot_mem 函数预分配大块内存, 需要重新编译内核•vmalloc 函数,内核代码使用它来分配在虚拟内存中连续但在物理内存中不一定连续的内存5、伙伴系统——反碎片机制1) 不可移动页•这些页在内存中有固定的位置,不能够移动,也不可回收•内核代码段,数据段,内核 kmalloc() 出来的内存,内核线程占用的内存等2)可回收页•这些页不能移动,但可以删除。
内核在回收页占据了太多的内存时或者内存短缺时进行页面回收3)可移动页•这些页可以任意移动,用户空间应用程序使用的页都属于该类别。
它们是通过页表映射的•当它们移动到新的位置,页表项也会相应的更新6、slab 算法——基本原理1)基本概念•Linux 所使用的 slab 分配器的基础是 Jeff Bonwick 为 SunOS 操作系统首次引入的一种算法•它的基本思想是将内核中经常使用的对象放到高速缓存中,并且由系统保持为初始的可利用状态。
比如进程描述符,内核中会频繁对此数据进行申请和释放2)内部碎片•已经被分配出去的的内存空间大于请求所需的内存空间3) 基本目标•减少伙伴算法在分配小块连续内存时所产生的内部碎片•将频繁使用的对象缓存起来,减少分配、初始化和释放对象的时间开销•通过着色技术调整对象以更好的使用硬件高速缓存7、slab 分配器的结构•由于对象是从 slab 中分配和释放的,因此单个 slab 可以在 slab 列表之间进行移动•slabs_empty 列表中的 slab 是进行回收(reaping)的主要备选对象•slab 还支持通用对象的初始化,从而避免了为同一目而对一个对象重复进行初始化8、slab 高速缓存1)普通高速缓存•slab 分配器所提供的小块连续内存的分配是通过通用高速缓存实现的•通用高速缓存所提供的对象具有几何分布的大小,范围为 32 到 131072 字节。
•内核中提供了 kmalloc() 和 kfree() 两个接口分别进行内存的申请和释放2)专用高速缓存•内核为专用高速缓存的申请和释放提供了一套完整的接口,根据所传入的参数为具体的对象分配 slab 缓存•kmem_cache_create() 用于对一个指定的对象创建高速缓存。
它从cache_cache 普通高速缓存中为新的专有缓存分配一个高速缓存描述符,并把这个描述符插入到高速缓存描述符形成的 cache_chain 链表中•kmem_cache_alloc() 在其参数所指定的高速缓存中分配一个 slab。
相反,kmem_cache_free() 在其参数所指定的高速缓存中释放一个 slab9、内核态内存池1)基本原理•先申请分配一定数量的、大小相等(一般情况下) 的内存块留作备用•当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存•这样做的一个显著优点是尽量避免了内存碎片,使得内存分配效率得到提升2)内核 API•mempool_create 创建内存池对象•mempool_alloc 分配函数获得该对象•mempool_free 释放一个对象•mempool_destroy 销毁内存池10、用户态内存池1) C++ 实例11、DMA 内存1)什么是 DMA•直接内存访问是一种硬件机制,它允许外围设备和主内存之间直接传输它们的 I/O 数据,而不需要系统处理器的参与2) DMA 控制器的功能•能向 CPU 发出系统保持(HOLD)信号,提出总线接管请求•当 CPU 发出允许接管信号后,负责对总线的控制,进入 DMA 方式•能对存储器寻址及能修改地址指针,实现对内存的读写操作•能决定本次 DMA 传送的字节数,判断 DMA 传送是否结束•发出 DMA 结束信号,使 CPU 恢复正常工作状态2) DMA 信号•DREQ:DMA 请求信号。
是外设向 DMA 控制器提出要求,DMA 操作的申请信号•DACK:DMA 响应信号。
是 DMA 控制器向提出 DMA 请求的外设表示已收到请求和正进行处理的信号•HRQ:DMA 控制器向 CPU 发出的信号,要求接管总线的请求信号。
•HLDA:CPU 向 DMA 控制器发出的信号,允许接管总线的应答信号:四、内存使用场景out of memory 的时代过去了吗?no,内存再充足也不可任性使用。
1、内存的使用场景•page 管理•slab(kmalloc、内存池)•用户态内存使用(malloc、relloc 文件映射、共享内存)•程序的内存 map(栈、堆、code、data)•内核和用户态的数据传递(copy_from_user、copy_to_user)•内存映射(硬件寄存器、保留内存)•DMA 内存2、用户态内存分配函数•alloca 是向栈申请内存,因此无需释放•malloc 所分配的内存空间未被初始化,使用 malloc() 函数的程序开始时(内存空间还没有被重新分配) 能正常运行,但经过一段时间后(内存空间已被重新分配) 可能会出现问题•calloc 会将所分配的内存空间中的每一位都初始化为零•realloc 扩展现有内存空间大小a)如果当前连续内存块足够 realloc 的话,只是将 p 所指向的空间扩大,并返回p 的指针地址。