[Linux内核完全剖析]第五章Linux内核体系结构5.1-5.3总结 Linux内存空间分配

本文主要是介绍[Linux内核完全剖析]第五章Linux内核体系结构5.1-5.3总结 Linux内存空间分配,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Linux内核是宏/单内核,分5个模块:进程调度模块、内存管理模块、文件系统模块、进程间通讯模块、网络接口模块。

三种地址概念:
虚拟地址(Virtual Address)、逻辑地址(Logical Address):是程序产生的。虚拟地址由段选择符和段内偏移两部分组成,段内偏移又称逻辑地址。需根据GDT和LDT进行分段变换才能进行下一步地址处理。x86可以索引2^14个段选择符,每个段最长2^32B,最大虚拟地址空间为2^46(64T)B。

线性地址(Linear Address):是虚拟地址到物理地址转化的中间层,是处理器可寻址的内存空间中的地址,由逻辑地址加上对应段基址得到。如未开启分页机制,就等于物理地址。x86中线性地址空间为4GB。

物理地址(Physical Address):是在CPU地址线和其他外部总线上的地址信号。

Linux0.11内核,限制了GDT最大表项为256个,其中2项空闲(NULL/syscall),2项系统使用(Kernel Code/Data),每个进程使用两项(LDT,TTS)。但系统定义了最大进程数是64个,每个进程逻辑地址范围是64M,在线性地址空间中的起始位置是64MB*进程号,全部进程使用的地址空间是64*64MB=4GB。每个进程的代码段和数据段是完全重叠的。其中进程0和进程1比较特殊,分别占用了线性地址0和64M开头的640K地址,进程0还处于内核区。进程2开始就占用128MB开始的64MB空间,依次类推。

Linux0.11内核中,head.s把内核代码段和数据段都初始化为从线性地址0开头的16MB空间,包括内核所有的代码、内核段表(GDT、IDT、TTS)、页目录表和内核二级页表、内核局部数据以及临时栈(将被用于进程0的用户栈)。其中内核使用了4个二级页表和4项页目录,把0-16MB的线性地址映射到物理空间,而且其物理空间等于线性空间。但如果物理内存不满16MB,那么线性地址就不会映射到超过物理大小的内存上去。

进程0:系统中第一个启动的进程,它的代码段和数据段均在内核中,长度为640K,占用线性和物理地址空间中中的0——640K-1的范围。使用的是内核中的页目录和页表(内核页表是用户可读写的),对应的TSS0也是事先设置好的,位于sched.c文件中,长度为104字节。


进程1:(init进程)的代码也在内核代码区中,但当使用fork()来创建它的时候申请了一页内存作为二级页表,并复制了父进程(进程0)的页目录项和页表。它占用了64M——128M-1(实际使用为64M——64M+640K-1的范围)的线性空间,并映射到0——640K-1的物理空间,跟进程0使用的范围一样,长度也是640K。系统还为init进程申请一页内存放置任务数据结构(包括TSS)和init进程的内核态栈。init进程的用户态栈共享了进程0的用户态堆栈。但在init进程执行时,其用户态堆栈对应页表项被设置位只读,这是系统会分配新的页面给其使用。

进程N:使用fork()从init进程产生其他进程时,其过程和从进程0 fork()出init进程基本一致(只有对应的线性空间不同)。然后调用execve()开始加载进程映像的时候,是释放掉从任务1复制的页目录和页表表项以及对应的内存页面,然后重新设置相关页目录和页表。分配给的内存并不是立即生效,而是在需要访问的时候引发缺页异常,系统才会真正的分配物理内存给进程,这被称为Load on demand策略。

用户申请内存:使用库函数malloc()申请内存时,malloc()函数内部会为用户维护一个内存使用表,由库函数自定义策略决定什么时候去系统申请内存,或者释放内存,以及申请和释放的数量。通常来讲如果用户请求分配内存,库函数先看自己库存的内存是否够用,不够用再去向系统申请一块恰当大小的内存(如页的整数倍);用户释放内存的时候库函数也不会立刻将其释放给操作系统,而是缓存起来,等待用户下次的分配请求,直到进程退出,才会把所有内存交还给系统。从系统中申请的内存同样遵守Load on demand策略,只有在用户去实际访问这块内存的时候,系统才会把物理内存映射到指定位置。

这篇关于[Linux内核完全剖析]第五章Linux内核体系结构5.1-5.3总结 Linux内存空间分配的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799616

相关文章

Linux镜像文件制作方式

《Linux镜像文件制作方式》本文介绍了Linux镜像文件制作的过程,包括确定磁盘空间布局、制作空白镜像文件、分区与格式化、复制引导分区和其他分区... 目录1.确定磁盘空间布局2.制作空白镜像文件3.分区与格式化1) 分区2) 格式化4.复制引导分区5.复制其它分区1) 挂载2) 复制bootfs分区3)

Springboot3 ResponseEntity 完全使用案例

《Springboot3ResponseEntity完全使用案例》ResponseEntity是SpringBoot中控制HTTP响应的核心工具——它能让你精准定义响应状态码、响应头、响应体,相比... 目录Spring Boot 3 ResponseEntity 完全使用教程前置准备1. 项目基础依赖(M

C# List.Sort四种重载总结

《C#List.Sort四种重载总结》本文详细分析了C#中List.Sort()方法的四种重载形式及其实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录1. Sort方法的四种重载2. 具体使用- List.Sort();- IComparable

SpringBoot项目整合Netty启动失败的常见错误总结

《SpringBoot项目整合Netty启动失败的常见错误总结》本文总结了SpringBoot集成Netty时常见的8类问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、端口冲突问题1. Tomcat与Netty端口冲突二、主线程被阻塞问题1. Netty启动阻

SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)

《SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)》本文总结了SpringBoot项目整合Kafka启动失败的常见错误,包括Kafka服务器连接问题、序列化配置错误、依赖配置问题、... 目录一、Kafka服务器连接问题1. Kafka服务器无法连接2. 开发环境与生产环境网络不通二、序

Linux服务器数据盘移除并重新挂载的全过程

《Linux服务器数据盘移除并重新挂载的全过程》:本文主要介绍在Linux服务器上移除并重新挂载数据盘的整个过程,分为三大步:卸载文件系统、分离磁盘和重新挂载,每一步都有详细的步骤和注意事项,确保... 目录引言第一步:卸载文件系统第二步:分离磁盘第三步:重新挂载引言在 linux 服务器上移除并重新挂p

python3中正则表达式处理函数用法总结

《python3中正则表达式处理函数用法总结》Python中的正则表达式是一个强大的文本处理工具,用于匹配、查找、替换等操作,在Python中正则表达式的操作主要通过内置的re模块来实现,这篇文章主要... 目录前言re.match函数re.search方法re.match 与 re.search的区别检索

Linux下屏幕亮度的调节方式

《Linux下屏幕亮度的调节方式》文章介绍了Linux下屏幕亮度调节的几种方法,包括图形界面、手动调节(使用ACPI内核模块)和外接显示屏调节,以及自动调节软件(CaliseRedshift和Reds... 目录1 概述2 手动调节http://www.chinasem.cn2.1 手动屏幕调节2.2 外接显

Linux(centos7)虚拟机没有IP问题及解决方案

《Linux(centos7)虚拟机没有IP问题及解决方案》文章介绍了在CentOS7中配置虚拟机网络并使用Xshell连接虚拟机的步骤,首先,检查并配置网卡ens33的ONBOOT属性为yes,然后... 目录输入查看ZFhrxIP命令:ip addr查看,没有虚拟机IP修改ens33配置文件重启网络Xh

linux实现对.jar文件的配置文件进行修改

《linux实现对.jar文件的配置文件进行修改》文章讲述了如何使用Linux系统修改.jar文件的配置文件,包括进入文件夹、编辑文件、保存并退出编辑器,以及重新启动项目... 目录linux对.jar文件的配置文件进行修改第一步第二步 第三步第四步总结linux对.jar文件的配置文件进行修改第一步进