精华内容
下载资源
问答
  • 内存分段

    2015-10-02 14:28:10
    如何用C语言将内存分段并设置其管理属性?
  • 偶然间看了一本书才发现,尼玛,原来内存分段的初衷,竟然这么简单,这里先抛出结论:内存分段机制是为了区别代码和数据,代码和代码放一起,数据和数据放一起。 分析 在上古时期(8086处理器),硬件内存非常小,...

    前言

    先吐槽一下,在学习汇编语言时,对于那些代码段、数据段什么的概念,简直就是跟天书一样,可能学的时候不上心,但是更大的原因可能还是教材太垃圾,老师讲的不够透彻,当然啦,也可能是自己太笨了,直到工作多年后,也觉得抽象,偶然间看了一本书才发现,尼玛,原来内存分段的初衷,竟然这么简单,这里先抛出结论:内存分段机制是为了区别代码和数据,代码和代码放一起,数据和数据放一起

    分析

    在上古时期(8086处理器),硬件内存非常小,程序一般是使用汇编语言编写,对于内存条的使用,必须要掰着手指头和脚指头省着用,所以不存在现在复杂的内存调度和管理算法,这里有两个前提背景:

    • 1、CPU执行指令是按照顺序执行的。
    • 2、对CPU而言,指令和数据编译后都是机器码,所以CPU并不能区别这个机器码到底是指令还是数据,因为机器码是有限的,就是一个十六进制数而已,执行指令时,就认为机器码是指令,而执行数据操作时,则机器码就是数据。

    这样就带来一个问题:如果在指令中混杂了数据,会导致CPU不能正常工作,所以指令和数据需要分开存放,分别位于内存中的不同区域,存放指令的区域叫代码区, 存放数据区的叫数据区,为了让CPU正确识别和执行指令,程序员需要精心安排,并告诉处理器要执行的指令位于内存中的位置。intel也为这两个概念设计了4个寄存器:

    CS段寄存器

    CS 代码段(code segment)寄存器,专门存储代码段的寄存器,她与指针寄存器IP配合使用。

    DS段寄存器

    DS 数据段(data segment)寄存器,专门存储数据段的寄存器,它与DI变址寄存器配合使用。 代码示例:

    ; ax 存放内存中 数据段开始地址
    mov ax, 100H
    ; 将 ax 中的值 存入 ds数据段寄存器
    mov ds, ax
    ; di 寄存器中存入偏移地址 0
    mov di, 0
    

    SS栈段寄存器

    SS栈段(stack segment)寄存器,专门用来存储栈数据的寄存器,它与BP变址寄存器配合使用。

    ES附加段寄存器

    ES附加段(extension segment)寄存器,这里用“附加”解释还是有些不准确,应该是扩展段寄存器,相当于是CS段寄存器的备用,ES寄存器专门配合数据内存地址,比如我们对于 显卡显存的操作,其实就可以通过ES寄存器指向显存段,它与DI变址寄存器配置使用。

    小结

    CPU硬件和软件发展到现在,与最早的CPU已经天差地别,但是intel为了保持兼容性,保留了很多原始的概念,内存分段最原始的原因就是为了区别代码和数据,将程序功能分段,分区间连续的存放,避免出错。

    展开全文
  • 内存分段和内存碎片 我们电脑肯定是要执行好多个程序的,在内存里面肯定占用多个连续的分段,但是假如其中一个程序退出,假如又来了一个程序小于剩余的空间,但是又没有连续的空间可以放下,显然这个程序无法执行。 ...

    程序如何执行

    程序通过链接器,多个文件合并成一个最终可执行文件。可执行程序加载后占用的内存空间应该是连续的,因为执行指令的时候,程序计数器是顺序地一条一条指令执行下去。这也就意味着,这一条条指令需要连续地存储在一起。

    内存分段和内存碎片

    我们电脑肯定是要执行好多个程序的,在内存里面肯定占用多个连续的分段,但是假如其中一个程序退出,假如又来了一个程序小于剩余的空间,但是又没有连续的空间可以放下,显然这个程序无法执行。

    举个列子:假如内存100K,我已经运行了4个20K的程序,内存分配这样:程序1(20K)、2(20K)、3(20K)、4(20K)、剩余20K,程序3退出后,剩余40K,但是剩余2个20K连续的分段,如程序5是30K,显然无法运行了,这就是内存碎片。

    内存交换

    上面的问题是如何解决的?假如我们把程序4向前移动20K内存的距离,将会剩下一段40K的连续内存,程序5就可以运行了。 哈哈,这就是内存交换。
    他是如何做的?先把程序4写到硬盘上,然后硬盘上再写到移动位置的内存上,我们都知道LINUX系统上有一个SWAP内存交换区吧,它就干这个的。
    但是由于IO性能的问题,比内存的读写慢好多倍,导致了机器的卡顿。

    内存分页

    由于内存交换导致了机器的卡顿,如果我们把每次交换的容量减少呐,这样性能将会有极大的提升,于是我们把连续的内存进行分页,分成许多个几K的页,提出交换速度。
    我们把程序分成好多页,并把分页信息,存放在虚拟内存中(硬盘上),通常分页大小和物理内存分页大小一样,如果程序需要执行的代码页在内存中便会执行,如果不在会触发缺页,回到虚拟内存中找到缺页,加载到内存去执行。设计一个好的页面置换算法至关重要。

    在Linux下,我们通常只设置成4KB。
    由于内存空间都是预先划分好的,也就没有了不能使用的碎片,而只有被释放出来的很多4KB的页。
    理论上计算机可以执行无数的程序,并不受限于内存大小。通过内存分页+虚拟内存+内存交换组合,我们最终得到了一个让程序不需要考虑实际的物理内存地址、大小和当前分配空间的解决方案。

    展开全文
  • 虚拟内存分段

    2017-12-30 21:06:15
    虚拟内存分段 大神链接:http://m.blog.csdn.net/gatieme/article/details/43567433 (存储类 作用域 生命周期 链接属性) 32位ubuntu下查看虚拟内存: mem代表的是真实的内存 swap则是虚拟内存 虚拟内存是...

    虚拟内存分段

    大神链接:http://m.blog.csdn.net/gatieme/article/details/43567433

    (存储类 作用域 生命周期 链接属性)

    32位ubuntu下查看虚拟内存:
    这里写图片描述
    mem代表的是真实的内存 swap则是虚拟内存 虚拟内存是可以设置的 一般设置为真实内存的1-1.5倍。

    (1)栈区(由编译器自动分配释放)

    栈上的变量描述的关键字 auto(声明自动变量,缺省时编译器一般默认为auto)
    栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。

    除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。

    由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

    (2)堆区(程序员自己手动,程序结束自动)

    malloc+realloc+calloc等函数申请的内存空间在堆上,又程序员自己申请,自己释放。

    (3)代码段

    函数的代码(main函数,子函数等等),char*p=‘’12345‘’(可能在只读段,也有可能在代码段,看编译器而定)

    (4)只读段

    只读段存放的是 const修饰的变量

    (5)文件映射区

    当你进程打开一个文件,就在内存中有了一个副本,更新或者操作了这个文件,保存一下,就存在在了你的硬盘之上。

    (6)内核区

    各自的进程彼此之间是看不见的,独享你的整个虚拟内存,所以各自的进程里,都有一个内核。

    (7)data段

    data段存放的数据:
    (1)static修饰的显式初始化为非0的局部变量
    (2)显式初始化为非0的全局变量

    (8).bss段

    .bss段存放的是:
    (1)static修饰的初始化为0或者不初始化的局部变量
    (2)初始化为0或者不初始化的全局变量

    这里写图片描述


    堆和栈的对比

    栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率有一定降低。栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放函数。为可移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/ 释放内存匹配是良好程序的基本要素。

    1.碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以>参考数据结构,这里我们就不再一一讨论了。

    2.生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

    3.分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。

    4.分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

    展开全文
  • 文章目录C语言一.简介二.程序的内存分配三....我我先看一下详细的内存分段 用户所使用的内存分段 平时我记着都是这五段 栈, 堆,未初始化数据,数据,代码段 不同的地方可能分法略有差异 C/C++...

    C语言

    一.简介

    学习C语言,我们得先了解一下,我们所写的程序的本质,我定义的变量去了哪里,我们申请的空间存储在哪里,今天就来给大家简绍一下

    二.程序的内存分配

    我我先看一下详细的内存分段
    在这里插入图片描述
    用户所使用的内存分段
    在这里插入图片描述
    平时我记着都是这五段
    栈, 堆,未初始化数据,数据,代码段

    不同的地方可能分法略有差异

    C/C++编译的程序占用的内存分为以下几个部分

    • 1、栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

    • 2、堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。

    • 3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束后由系统释放。

    • 4、文字常量区:常量字符串就是放在这里的。程序结束后由系统释放

    • 5、程序代码区:存放函数体的二进制代码。

    三.静态内存和动态内存

    静态内存分配好后,程序运行过程中一直存在不会被释放,且一旦分配好,其内存大小就固定下来不能改变,在编译和链接的阶段就会分配好。

    动态内存是程序运行过程中,根据程序的需要分配和释放,其大小可变。

    四.堆和栈

    在这里我们记住这句话,小栈大堆

    就像之前看到一个新闻,某程序员因为大量来定义变量,写程序,被公司告了,不知道为什么往下看就明白了

    堆和栈都是动态分配的,区别有两点:

    1. 栈是由编译器分配与释放,速度比较快,堆是程序通过调用malloc或new分配,速度比较慢,调用free或delete释放。

    2. 栈是线性结构,堆是链表结构。

    五.应用

    • 全局变量和static修饰的静态变量都存放在静态内存区。
    • 函数内部定义的局部变量,存储在栈上,函数退出时,其占用内存被收回。
    • 通过调用malloc或new得到的内存在堆上,不再需要时要显示的调用free或delete来释放,否则会操作内存泄漏

    程序说明

    #include <stdio.h>
    
    int a = 0;  //全局初始化区 ,静态内存
    char *p1;  //全局未初始化区 ,静态内存
    
    int main() 
    { 
    	int b;  //栈 
    	const c; //栈
    	
    	char s[] = "abc";  //栈 
    	char *p2; // 栈 
    	
    	char *p3 = "123456";  //"123456\0"在常量区,静态内存,注意p3在栈上 
    	
    	static int c =0//全局(静态)初始化区 
    	
    	p1 = (char *)malloc(10); 
    	p2 = (char *)malloc(20); 
    	//分配 得来的10和20字节的区域就在堆区。 
    	
    	strcpy(p1, "123456");  //"123456\0"放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 
    } 
    

    这里要特别注意一下

    • const修饰的变量原来在哪,修饰完后还在哪,比如修饰全局变量,放在数据段,修饰局部变量,放在栈区

    • static 修饰的不管是全局变量还是局部变量都存在于全局变量区域,数据段

    在这里我们可以形象的理解,栈区的数据就像我们去饭店吃饭,告诉老板我们吃什么就好了,吃完直接就走,不用管碗谁来洗,桌子谁来收拾,
    而在堆区,就像我们自己做饭,安装自己的口味来做自己特别喜欢的佳肴,吃完饭自己收拾所有的一切

    展开全文
  • 无用的内存分段

    2019-09-24 02:27:58
    分段是80X86体系的处理器支持的一种特性,也就是说硬件已经支持了这内存分段的功能, 用或不用的选择权在操作系统手中,linux系统就没有使用分段的功能,而使用了分页的功能。 linux虽然没有用分段,但了解分段对于...
  • 一、c语言内存分段 区域 内容 栈 局部变量、函数参数、函数返回值 堆 malloc/free 全局/静态存储区 初始化和未初始化的全局变量和静态变量、是否初始化分开存放 常量存储区 常量 二、c++内存分段 ...
  • 内存分段与分页

    2017-11-23 23:10:00
    内存分段与分页机制 因为实际物理内存与应用程序的大小之间的差别往往非常大,应用程序本身的大小甚至经常超过物理内存的大小,因此引入了虚拟内存的概念,使用分页机制把二者结合起来。分页各个页大小固定,也有...
  • 3-浅谈8086CPU的内存分段机制

    千次阅读 2018-12-10 22:39:09
    1. 内存分段 在上一篇我们知道8086CPU在访问内存使用了分段机制,即通过“(段地址×16)+偏移地址=物理地址”的方式来确定内存单元的物理地址,需要明白的是内存空间是一个连续的线性空间,对于内存本身来说并没有...
  • 参考:内存分段和分页的区别https://blog.csdn.net/u011740322/article/details/10081495 分段和分页其实都是一种对地址的划分或者映射的方式。 两者的区别主要有以下几点:...
  • 内存分段管理 实模式下的内存地址变换 提示:这是重点,为汇编打基础 一、内部存储器管理 可以同时产生16位二进制码 可以产生64K编码(直接管理64K个内存单元) 而8088CPU需要管理1MB的内存(需要1M个) 所以16*...
  • class A { int a; unsigned char b:1; unsigned char c:1; }; 和 class B {int a; unsigned char b:1; public: unsigned char c:1; }; 为什么他们的size都是8?...public的出现并未让他们内存分段...
  • linux 内存分段机制

    2011-09-20 13:15:20
    内存分段机制 在内存分段系统中,一个程序的逻辑地址通过分段机制自动地映射(变换)到中间层的4GB(232B)线性地址空间中。程序每次对内存的引用都是对内 存段中内存的引用。当程序引用一个内存地址时,通过把...
  • 阅读此文,先熟悉x86体系早期的实模式下的内存分段的地址映射。 正是由于在实模式下直接对物理内存进行读写,非常不安全,所以诞生了新的内存分段的映射方式,其目的就是对物理内存进行保护,而对内存进行保护需要...
  • 内存分段机制

    2020-05-07 17:37:49
    参考 《深入理解计算机系统》 7.9 加载可执行目标文件 《Linux 内核0.11完全注释》 4.3 分页机制(进阶) 操作系统(哈工大李治军老师)32讲(全)超清 P20 L20 内存使用与分段 GDT(全居描述符表)和LDT(局部描述...
  • 操作系统内存分段机制

    千次阅读 2013-04-07 15:46:17
    内存分段系统中,一个程序的逻辑地址通过分段机制自动地映射(变换)到中间层的4GB(2^32B)线性地址空间中。程序每次对内存的引用都是对内存段中内存的引用。当程序引用一个内存地址时,通过把相应的段基址加到...
  • 内存分段(笔记)

    千次阅读 2011-08-16 19:56:30
    内存分段(笔记) 在冯诺依曼的体系结构中必须有:代码段,堆栈段,数据段 因为冯氏结构,本质就是取址,执行的过程 编译器和系统在为变量分配是从高地址开始分配的. 全局变量和函数参数在内存中的存储...
  • 内存分段与分页机制

    千次阅读 2015-08-19 15:38:13
    系统内存分页和分段地址管理
  • 区别:没有绝对的联系,他们属于两个学科的各自命名,内存分段区域中的是操作系统的专有名词 联系:数据结构的栈与系统分段栈(函数栈帧)中的对象都符合先进后出
  • 内存分段分页机制理解

    千次阅读 2019-08-29 08:14:30
    现代操作系统,计算机内存是按照先分段再分页的方式管理的。 注意: 以下描述都是基于32位计算机进行描述的。 1. 分段 1) 程序直接使用物理地址的问题 考虑最原始,最直接的情况,程序中访问的地址都直接对应于物理...
  • struct ldt_struct { struct desc_struct *entries; //段表项结构 unsigned int nr_entries; int slot; };

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 77,359
精华内容 30,943
关键字:

内存分段