malloc过大,缺页中断

内存分配原理:

当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作:
1、检查要访问的虚拟地址是否合法
2、查找/分配一个物理页
3、填充物理页内容(读取磁盘,或者直接置0,或者啥也不干)
4、建立映射关系(虚拟地址到物理地址)
重新执行发生缺页中断的那条指令
如果第3步,需要读取磁盘,那么这次缺页中断就是majflt,否则就是minflt。

如何查看进程发生缺页中断的次数:
ps -o majflt,minflt -C program
          
majflt代表major fault,中文名叫大错误,minflt代表minor fault,中文名叫小错误。
这两个数值表示一个进程自启动以来所发生的缺页中断的次数。

malloc的工作原理

malloc函数分配内存主要是使用brk和mmap系统调用

brk():		小于128k
	将数据段(.data)的最高地址指针_edata往高地址推;
mmap():		大于128k
	是在堆和栈之间(文件映射区域)找分配一块空闲的虚拟内存,

都是虚拟内存,没有分配物理内存。
在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存,
然后建立虚拟内存和物理内存之间的映射关系。

内核为用户进程分配内存的特点

1)内核中只要请求内存得以满足,都会返回页描述符的地址或线性地址
2)当用户态进程申请动态内存时,并没有获取请求的页框,而是获得一个线性区,(malloc())
当第一次访问分配的线性区的时候,(因为线性区没有那么大)发生缺页中断,
为线性区分配物理内存,最后建立虚拟地址和物理地址的映射
	
原因:进程对动态内存的请求认为是不紧迫的,内核总是推迟给用户态进程分配动态内存。
由于用户态进程是不可信任的,内核必须随时准能被捕获用户态进程引起的寻址错误

free的工作原理

对内存块进行了 free 调用之后,这块内存标记为未被使用,但是堆的内存还是没有释放

举例,假射系统调用brk先分配了内存A,然后在分配内存B,系统调用mmap分配了内存C
       如果free由mmap分配的内存C,直接将C中的虚拟内存和物理内存释放回给操作系统
       如果free有brk分配的A,A的虚拟内存和物理内存都没有释放,但是A的内存可以重用	//但内存没有被释放
       如果再释放brk分配的B,如果A和B的内存和大于128k,
       则将A和B的虚拟内存和物理内存都释放回给操作系统,否则也没有释放。	//连续的未使用的内存大于128k时一起释放

为什么等到第一次访问虚拟内存的时候才分配物理内存呢
因为申请的内存不一定马上使用,推迟分配可以系统拥有更多的空闲物理内存去出来其他事,从而提高系统的吞吐量。


为什么达到128k才释放呢:			//堆的内存分配算法多种多样
因为小于128k的内存并不够mmap分配,不释放,下次申请小内存时,直接重用该内存即可。
大于128k,可以释放该内存,以便mmap函数可以分配该内存。

程序执行时的内存分配(虚拟内存)

在这里插入图片描述

白色区域:防止攻击者猜测到段的起始地址,发起远程攻击。(没有映射到物理内存上,实际不占内存空间)
由上到下:
kernel space:内核预留的的一段虚拟内存空间,
(内核的空间的页表有特殊flag,内核空间在所有程序中指向的物理地址是一样的,
内核代码总是可寻址的.随时接受中断或系统调用. 与此相反用户的地址空间则会随着进程的切换不断变化)
:
	调用一个新的函数,会在栈上创建一个新的栈帧,每当函数返回值这个栈帧会被自动销毁.
	严格遵循LIFO的顺序,不需要复杂的数据结构来跟踪栈地址,只需要一个栈顶指针可以搞定.
	栈空间一直重复使用(push\pop)有利于栈内存活跃在cpu cache中加快访问速度.

	栈空间用尽后继续push数据会触发栈空间的扩展. 这会触发一个 page fault 然后在内核中调用expand_stack()函数.
	该函数调用acct_stack_growth()来判断是否可以增长占空间. 
	如果当前栈空间的大小小于RLIMIT_STACK(8M),可以继续增长栈空间. 该过程由内核完成进程不会感知到.
	当用户的占空间已经达到允许的最大值时,内核会给进程发送一个Segmentation Fault信号终止该进程.  
	进程的栈空间只会增大不会缩小,有点像联邦运算,只增不减.
mmap区域:
	在这些区域中内核将文件直接映射到地址空间中. 应用程序可以显示创建这些区域,通过调用mmap()/CreateFileMapping()/MapViewOfFile(). 
	内存映射是一种高效和方便操作文件的一种方式, 所以内存映射通常被用来加载动态链接库. 
	malloc 一个非常大块的内存,标准c库会通过mmap来创建这块内存区间而不使用Heap内存, (>128k)
//不同与数据结构中的堆,更类似于链表
	堆提供了程序运行时的内存分配, 堆内存的生命周期在函数之外. 
	当前堆的内存足够程序使用,在当前堆中寻找可用内存就行,.
	否则的话需要调用brk()系统调用在内核中增大堆内存. 
.data	已初始化的
.bss	未初始化的
.text	常量,及汇编代码
保留区	用于捕捉异常(空指针,非法引用)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值