new深入详解、linux内核

4 篇文章 0 订阅
2 篇文章 0 订阅

前言

笔者最近在阅读grpccpp部分源码时,发现了一种笔者未见过的new用法,是笔者阅读甚少了。借此机会,分享给大家,以笔者浅薄的理解,简单探讨一下new内存分配及相关的理论。

接下来便以示例代码做演示。

示例代码

#include <iostream>
#include <new>
#include <string>
#include <memory>
#include <limits.h>

#pragma pack(1)

class Test {
 public:
 	Test(std::string& name) : name_(name) { }
 	virtual ~Test() {}
 
 private:
 	std::string name_;	
};

int main(int argc, char *argv[])
{
	uint8_t mem[sizeof(Test)];

	/* 一般用法 */
	Test *t1 = new Test(std::string("test1"));
	
	/* 二般用法,在指定内存区域初始化对象 */
	Test *t2 = new (mem) Test(std::string("test2"));
	
	delete t1;
	
	return 0;
}

如上面的代码所示,上面的new用法有两种:

  1. 一种是常用的用法,其实包含了两个步骤,即先分配内存,然后调用类构造函数初始化对象
  2. 另外一种用法是使用new指定的内存调用类的构造函数进行对象布局的初始化,这种初始化需要保证目标内存块大小>=类对象的内存大小,包含内存对齐

内存分配

除此之外,也分享一下关于malloc | freenew | delete的简单认识:

  1. malloc | freeC语言提供的内存分配函数。new | delete属于cpp里面提供的内存操作符。
  2. malloc分配的内存是未初始化的。new分配的内存是已初始化的,因为new其实是先分配内存然后再初始化
  3. malloc返回的是void*指针,需要void*强制转换至目标类型指针new返回的是目标类型指针
  4. new | delete其实是基于malloc | free来实现的。

new步骤:

  1. 使用全局的new分配指定内存,以类为例,会分配相应对象大小的内存;
  2. 以对象为例,在步骤1分配的内存调用类的构造函数进行对象初始化;

delete步骤(其实是调用类的删除析构函数,删除析构函数包含下面两个步骤):

  1. 调用类的析构函数,销毁对象布局。
  2. 调用全局的delete释放指定内存。

malloc | free的实现:

基于linux操作系统而言,在笔者阅读过的早期linux内核源码(0.11 或 0.96版本),操作系统层面的内存管理中,内存是以页的形式组织,内存页的大小一般为4096字节,将页内存划分成各种不同大小的内存块,对应大小的内存块挂到对应链表头,以链表形式组织。形式如下图:

在这里插入图片描述

  • 调用malloc时,根据所需内存大小找到刚好满足需求(当前链表头内存块大小 >= 所需内存大小)的链表头,再遍历链表找到第一块空闲的内存块。

  • free时,根据传入的地址,换算得到对应内存页的地址,根据内存页找到对应的内存块描述结构体,将当前内存块挂到全局的空闲内存链表上,如果当前释放地址对应的内存页的引用计数为0,则将当前内存页的内存释放。

  • 关于malloc,则需要聊下glibc库的mallocglibc提供的malloc分配内存时,其实是分配了块大小略微大于所需的内存块,在整个内存块的前面一块内存记录着当前所分配内存的大小返回给用户的地址其实是glibc拿到的内存块的地址稍微偏后的内存地址,这也就是为什么free只需传入释放内存的地址而不需要传入内存块大小就能释放内存的原因。

  • 前面所述关于操作系统的内存管理是内核比较古老的版本(0.11 或 0.96 版本),与现代linux操作系统的内存管理细节上估计有所不同,现代linux操作系统已引入了虚拟内存段页式内存管理等等。

  • 笔者认为,学习早期linux内核,是一种让你快速理解操作系统相关原理的方式。早期linux内核源码代码量较少,易于阅读理解。

  • 关于古老版本的内核源码可从赵炯博士维护的oldlinux网站获取,网站地址http://www.oldlinux.org/或点击链接。学习linux内核时,可搭配赵炯博士写的linux内核源码剖析来看。

结尾

  • 行文至此,关于new的分享已结束了。若有错误之处,欢迎指正。
  • 如果觉得还不错,你的点赞关注加收藏便是笔者继续更新的最大动力哦^_^
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值