首先谢谢 @dudu 和 @张善友 这2位大神能订阅我,本来在写这个系列以前,我一直对写一些核心而且底层的知识持怀疑态度,我为什么持怀疑态度呢?因为一般写高层语言的人99%都不会碰底层,其实说句实话,我以前也不看这些东西,只是因为自己觉得对C++感兴趣,索性乱写点东西,如果有写得不好的地方,还请上面2位大神指出。

  其实我现在虽然写的是C++,但是我打算在后面把C++和.NET的一些基础类库融合起来,我发现写CLR的文章特别少,不知道什么原因。反正,废话不多,开始今天的写作吧,今天依然是把重点集中在GC上面。

  首先跟大家分享一下我这次碰到的一个有趣的东西,就是下面的东西,下面的东西我第一次看,不过我可以确定的是,GC的运行模式有以下。以下都有注释,我就不详解了,不过跟大家说一下我的一个小小的发现:我猜测,以下代码只在64位GC下运行,这句话听起来很拗口,但是我是怎么得到这个结论的呢?

// !!!!!!!!!!!!!!!!!!!!!!!
// make sure you change the def in bcl\system\gc.cs
// if you change this!
//上面那句ENGLISH的意思就是如果要改这里面的值,必须先改变bc1\system\gc.cs里面的定义
//收集器运行模式
enum collection_mode
{
collection_non_blocking = 0x00000001, //非锁定模式
collection_blocking = 0x00000002, //锁定模式
collection_optimized = 0x00000004, //优化模式
collection_compacting = 0x00000008 //最小适配模式 #ifdef STRESS_HEAP //如果定义了Stress_heap,我这里翻译为压力堆,也就是“入堆”
, collection_gcstress = 0x80000000 //这里我觉得应该是GC可以入堆的一个条件吧,虽然我不懂这个是什么意思
#endif // STRESS_HEAP
};

  

  虽然我不敢完全说我是对的,但是有一点可以确定,就是它会生成x64,以windows内核为寄托的一个以i结尾的文件,我们可以把它理解为一个临时文件,而GC和windows内存的关系就像一个寄宿关系一样,GC是依赖于windows内核的某个东西生存(全是个人的猜测)。

  那么,这些enmu类型的固定值,在GC当中,到底起了一个什么样的作用呢?我随便找了几个变量,因为这些固定值,其实在GC当中,你可以理解它是无处不在的,就相当于平常写代码的if else 一样普通,大家知道这些变量的用处就行了,不必过于纠结代码是什么意思,因为以后我会带大家慢慢研究。

//如果定义成了后台GC
#ifdef BACKGROUND_GC
if (recursive_gc_sync::background_running_p())
{
//如果mode(暂时可以理解为一个变量)
//collection_non_blocking 值是0x00000001,也就是说mode&collection_non_blocking其实只要比较最右边一位就OK了,也就是mode=1 or 4
if ((mode == collection_optimized) || (mode & collection_non_blocking))
{
return S_OK;
}
if (mode & collection_blocking)
{
pGenGCHeap->background_gc_wait();
if (mode & collection_optimized)
{
return S_OK;
}
}
}

  今天我也不想过多的浪费时间,我打算挑一个有代表性的代码片段来带大家了解GC,所谓GC,GC是什么,那么它肯定有一个Collect的方法;好,那我们就拿这个方法开刀吧。首先我们必须知道几个知识点,对于非c++程序员来说,也还是需要学一点东西,size_t的解释,在这里简单一点说就是long unsigned  int ,我为什么特意把long标红呢?因为我们的GC使用的方法,是在64位环境下运行的,如果是32位的,那么就是unsigned int .

  因为这段代码很长,所以我打算:先讲一部分,然后再讲剩下的部分,不然大家就算看注释,也会眼花的。

//函数返回值。如果这个函数是执行完返回的话将包含具有实际意义的数据,如果立即返回则包含状态信息--发送成功与否 -来自百度
HRESULT //generation(代,比如你和你父母是2代人)
//
GCHeap::GarbageCollect (int generation, BOOL low_memory_p, int mode)
{
//如果定义了64位的。。。也就是说,此GC的CLR是在64位运行时上跑的
#if defined(BIT64) //如果定义了弱存储指针 PS:我也不知道怎么翻译,索性把low翻译成弱。
if (low_memory_p)
{
//1.初始化:所有已经分配的空间
size_t total_allocated = 0;
//所有“想要”分配的空间
size_t total_desired = 0; //如果定义了复杂堆(我自己翻译的)
#ifdef MULTIPLE_HEAPS
int hn = 0; //n_heaps这个定义我没找到,不过我可以确定的是,这个肯定是和MULTIPLE_HEAPS有关的
//大家可以把这个理解为MULTIPLE_HEAPS.Length
for (hn = 0; hn < gc_heap::n_heaps; hn++)
{
//首先是定义一个“临时”的指针hp,让gc堆当中的每一项都指向这个变量。
gc_heap* hp = gc_heap::g_heaps [hn]; //把每一块想要分配的数量,叠加起来。
total_desired += dd_desired_allocation (hp->dynamic_data_of (0)); //总分配量=想要分配的-新分配的
total_allocated += dd_desired_allocation (hp->dynamic_data_of (0))-
dd_new_allocation (hp->dynamic_data_of (0));
}

  大家需要从上面的代码当中,掌握如下几个基础知识点:

  一个是dynamic_data_of方法,它返回了一个dynamic_data类的指针变量,那我们乘胜追击,看看这个方法和类。

    PER_HEAP
dynamic_data* dynamic_data_of (int gen_number);

  首先是方法:

//返回dynamic_data_table的第一个Table,大家可以类比.net中的DataSet
inline
dynamic_data* gc_heap::dynamic_data_of (int gen_number)
{
return &dynamic_data_table [ gen_number ];
}

  然后我们再来看看这个dynamic_data_table,

    PER_HEAP
dynamic_data dynamic_data_table [NUMBERGENERATIONS+1];

  下面来看这张图,突然我恍然大悟,所谓的DataTable,就是我们每次使用的DataSet,其实底层是放在堆栈上面的,以复杂堆的方式存放,而每个DataTable,其实就是堆栈当中的小小的组成而已,不止我理解得对不对。

其中上面代码中的下面2个方法,都是和dynamic_data有关系的。其中ptrdiff_t类型变量通常用来保存两个指针减法操作的结果,这也是需要.NET程序员注意的,毕竟搞.NET是不和指针打交道的。

inline
size_t& dd_desired_allocation (dynamic_data* inst)
{
return inst->desired_allocation;
}
inline
ptrdiff_t& dd_new_allocation (dynamic_data* inst)
{
return inst->new_allocation;
}

  大家还要注意一下小细节,就是+=其实是先+=,再减去新分配的空间。

  今天就说这么多了,因为我还要做其他的事情,最后跟大家卖个关子,那些说.NET没技术含量的人,其实是不了解.NET原理的人。下面的就是一个比较复杂的类,这里面定义了超多的友元类,也就是说,GC表面上是一段代码,其实这就是一部重型航空母舰,需要我们去探索它的结构。

  爱因斯坦曾经说过一句名言:追求真理比占有真理更可贵。我们要做的,不仅仅是一颗螺丝钉。

C++随笔:.NET CoreCLR之GC探索(2)的更多相关文章

  1. C++随笔:.NET CoreCLR之GC探索(4)

    今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...

  2. C++随笔:.NET CoreCLR之GC探索(3)

    有几天没写GC相关的文章了哈,今天我讲GC的方式是通过一个小的Sample来讲解,这个小的示例代码只有全部Build成功了才会有.地址为D:\coreclr2\coreclr\bin\obj\Wind ...

  3. C++随笔:.NET CoreCLR之GC探索(1)

    一直是.NET程序员,但是.NET的核心其实还是C++,所以我准备花 一点时间来研究CoreCLR和CoreFX.希望这个系列的文章能给大家带来 帮助. GC的代码有很多很多,而且结构层次对于一个初学 ...

  4. CoreCLR源码探索(五) GC内存收集器的内部实现 调试篇

    在上一篇中我分析了CoreCLR中GC的内部处理, 在这一篇我将使用LLDB实际跟踪CoreCLR中GC,关于如何使用LLDB调试CoreCLR的介绍可以看: 微软官方的文档,地址 我在第3篇中的介绍 ...

  5. CoreCLR文档翻译 - GC的设计

    此文档来源于CoreCLR的BOTR(The Book of the Runtime), 点击打开原文 一切著作权归微软公司所有 GC的设计 作者: Maoni Stephens (@maoni0) ...

  6. CoreCLR源码探索(三) GC内存分配器的内部实现

    在前一篇中我讲解了new是怎么工作的, 但是却一笔跳过了内存分配相关的部分. 在这一篇中我将详细讲解GC内存分配器的内部实现. 在看这一篇之前请必须先看完微软BOTR文档中的"Garbage ...

  7. CoreCLR源码探索(四) GC内存收集器的内部实现 分析篇

    在这篇中我将讲述GC Collector内部的实现, 这是CoreCLR中除了JIT以外最复杂部分,下面一些概念目前尚未有公开的文档和书籍讲到. 为了分析这部分我花了一个多月的时间,期间也多次向Cor ...

  8. CoreCLR源码探索(一) Object是什么

    .Net程序员们每天都在和Object在打交道 如果你问一个.Net程序员什么是Object,他可能会信誓旦旦的告诉你"Object还不简单吗,就是所有类型的基类" 这个答案是对的 ...

  9. CoreCLR源码探索(二) new是什么

    前一篇我们看到了CoreCLR中对Object的定义,这一篇我们将会看CoreCLR中对new的定义和处理 new对于.Net程序员们来说同样是耳熟能详的关键词,我们每天都会用到new,然而new究竟 ...

随机推荐

  1. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  2. 旺财速啃H5框架之Bootstrap(四)

    上一篇<<旺财速啃H5框架之Bootstrap(三)>>已经把导航做了,接下来搭建内容框架.... 对于不规整的网页,要做成自适应就有点玩大了.... 例如下面这种版式的页面. ...

  3. 前端网络、JavaScript优化以及开发小技巧

    一.网络优化 YSlow有23条规则,中文可以参考这里.这几十条规则最主要是在做消除或减少不必要的网络延迟,将需要传输的数据压缩至最少. 1)合并压缩CSS.JavaScript.图片,静态资源CDN ...

  4. CodeSimth - .Net Framework Data Provider 可能没有安装。解决方法

    今天想使用CodeSimth生成一个sqlite数据库的模板.当添加添加数据库的时候发现: .Net Framework Data Provider 可能没有安装. 下面找到官方的文档说明: SQLi ...

  5. # PHP - 使用PHPMailer发邮件

    PHPMailer支持多种邮件发送方式,使用起来非常简单 1.下载PHPMailer https://github.com/PHPMailer/PHPMailer,下载完成加压后, 把下边的两个文件复 ...

  6. 【算法】C语言实现数组的动态分配

    C语言实现数组的动态分配 作者:白宁超 2016年10月27日20:13:13 摘要:数据结构和算法对于编程的意义不言而喻,具有指导意义的.无论从事算法优化方向研究,还是大数据处理,亦或者网站开发AP ...

  7. 记一次.NET代码重构

    好久没写代码了,终于好不容易接到了开发任务,一看时间还挺充足的,我就慢慢整吧,若是遇上赶进度,基本上直接是功能优先,完全不考虑设计.你可以认为我完全没有追求,当身后有鞭子使劲赶的时候,神马设计都是浮云 ...

  8. JavaScript将字符串中的每一个单词的第一个字母变为大写其余均为小写

    要求: 确保字符串的每个单词首字母都大写,其余部分小写. 这里我自己写了两种方法,或者说是一种方法,另一个是该方法的变种. 第一种: function titleCase(str) { var new ...

  9. Block解析(iOS)

    1. 操作系统中的栈和堆 我们先来看看一个由C/C++/OBJC编译的程序占用内存分布的结构: 栈区(stack):由系统自动分配,一般存放函数参数值.局部变量的值等.由编译器自动创建与释放.其操作方 ...

  10. 烂泥:wiki系统confluence5.6.6安装、中文、破解及迁移

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb confluence是一个专业的企业知识管理与协同软件,可以用于构建企业wiki.通过它 ...