C++随笔:.NET CoreCLR之corleCLR核心探索之coreconsole(2)
这篇文章是上篇的续集,本文将会继续介绍coreconsole.cpp里面的逻辑。也许大家会看一些CLR的书,我承认我没有看过,因为我觉得一个人,他再NB,那也是他自己的眼光,而且说句难听的,CLR也不是那个写书的人一个人完成的项目,所以他的眼光,我个人看来,也还是很有限的。 PS:谢谢@Grid Science 的建议
承接上篇文章的HostEnvironment,宿主环境:个人认为HOST是指的Windows内核。但是CLR有一个缺点,就是它并不是一个跨平台的,所以广义的说HOST应该是“操作系统内核”;下面我们来看看LoadCoreCLR这个方法,这个方法的核心宗旨就是从动态链接库当中得到CLR,如果出错,会记日志;
//尝试去“载入”CoreCLR,它带有一个coreCLR的路径
HMODULE TryLoadCoreCLR(const wchar_t* directoryPath) { //coreclr 路径
wchar_t coreCLRPath[MAX_LONGPATH];
//把形参赋给实参,也就是相当于coreCLRPath= directoryPath
wcscpy_s(coreCLRPath, directoryPath);
//把coreCLRDll,append到coreCLRPathd的后面,组成一个新的字符串
wcscat_s(coreCLRPath, coreCLRDll); //日志记录开始:尝试从路径载入CoreCLR
*m_log << W("Attempting to load: ") << coreCLRPath << Logger::endl; //LoadLibraryEx装载指定的动态链接库。
HMODULE result = ::LoadLibraryExW(coreCLRPath, NULL, 0); //载入失败的时候,记录日志
if (!result) {
*m_log << W("Failed to load: ") << coreCLRPath << Logger::endl;
*m_log << W("Error code: ") << GetLastError() << Logger::endl;
return nullptr;
} // Pin the module - CoreCLR.dll does not support being unloaded. //GetModuleHandleExW是获取一个应用程序或动态链接库的模块句柄
HMODULE dummy_coreCLRModule; //如果是GET_MODULE_HANDLE_EX_FLAG_PIN,则模块一直映射在调用该函数的进程中,直到该进程结束
if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, coreCLRPath, &dummy_coreCLRModule)) {
*m_log << W("Failed to pin: ") << coreCLRPath << Logger::endl;
return nullptr;
} wchar_t coreCLRLoadedPath[MAX_LONGPATH];
::GetModuleFileNameW(result, coreCLRLoadedPath, MAX_LONGPATH); *m_log << W("Loaded: ") << coreCLRLoadedPath << Logger::endl; //返回动态链接库
return result;
}
下面是HostEnvironment的构造函数,个人觉得主要的作用还是初始化,载入CoreCLR.
public:
// The path to the directory that CoreCLR is in
//CoreCLR的路径,注意区分“模块路径”和此路径的区别
wchar_t m_coreCLRDirectoryPath[MAX_LONGPATH]; //带有log参数的构造函数,并初始化LOG和CLR运行时
HostEnvironment(Logger *logger)
: m_log(logger), m_CLRRuntimeHost(nullptr) { // Discover the path to this exe's module. All other files are expected to be in the same directory.
//获得目录下EXE模块的路径的长度
DWORD thisModuleLength = ::GetModuleFileNameW(::GetModuleHandleW(nullptr), m_hostPath, MAX_LONGPATH); // Search for the last backslash in the host path. //寻找路径当中的最后一个分隔符"\\",如果找到了,就跳出循环
int lastBackslashIndex;
for (lastBackslashIndex = thisModuleLength-1; lastBackslashIndex >= 0; lastBackslashIndex--) {
if (m_hostPath[lastBackslashIndex] == W('\\')) {
break;
}
} // Copy the directory path //用m_hostDirectoryPath代替之前的路径目录的地址
::wcsncpy_s(m_hostDirectoryPath, m_hostPath, lastBackslashIndex + 1); // Save the exe name
//host 的EXE文件的名字,类似文件名,不过这里我有一个疑问:
//m_hostPath是一个字符型的指针,而lastBackslashIndex+1是数字,把它们2个加起来是什么意思?
m_hostExeName = m_hostPath + lastBackslashIndex + 1; *m_log << W("Host directory: ") << m_hostDirectoryPath << Logger::endl; // Check for %CORE_ROOT% and try to load CoreCLR.dll from it if it is set
//尝试从环境变量%CORE_ROOT%载入CoreCLR //coreRoot环境变量真实路径
wchar_t coreRoot[MAX_LONGPATH];
size_t outSize; //如果没有使用TryLoadCoreCLR方法的话,那么采用构造函数方式去初始化CoreCLR.
m_coreCLRModule = NULL; // Initialize this here since we don't call TryLoadCoreCLR if CORE_ROOT is unset. //取环境变量的值
if (_wgetenv_s(&outSize, coreRoot, MAX_LONGPATH, W("CORE_ROOT")) == 0 && outSize > 0)
{
wcscat_s(coreRoot, MAX_LONGPATH, W("\\"));
m_coreCLRModule = TryLoadCoreCLR(coreRoot);
}
else
{
*m_log << W("CORE_ROOT not set; skipping") << Logger::endl;
*m_log << W("You can set the environment variable CORE_ROOT to point to the path") << Logger::endl;
*m_log << W("where CoreCLR.dll lives to help this executable find it.") << Logger::endl;
} // Try to load CoreCLR from the directory that this exexutable is in
//从"目录"中尝试载入CoreCLR.
if (!m_coreCLRModule) {
m_coreCLRModule = TryLoadCoreCLR(m_hostDirectoryPath);
} //作用同上(thisModuleLength)
if (m_coreCLRModule) { // Save the directory that CoreCLR was found in
DWORD modulePathLength = ::GetModuleFileNameW(m_coreCLRModule, m_coreCLRDirectoryPath, MAX_LONGPATH); // Search for the last backslash and terminate it there to keep just the directory path with trailing slash
for (lastBackslashIndex = modulePathLength-1; lastBackslashIndex >= 0; lastBackslashIndex--) {
if (m_coreCLRDirectoryPath[lastBackslashIndex] == W('\\')) {
m_coreCLRDirectoryPath[lastBackslashIndex + 1] = W('\0');
break;
}
} } else {
*m_log << W("Unable to load ") << coreCLRDll << Logger::endl;
}
} //析构函数,释放coreclr
~HostEnvironment() {
if(m_coreCLRModule) {
// Free the module. This is done for completeness, but in fact CoreCLR.dll
// was pinned earlier so this call won't actually free it. The pinning is
// done because CoreCLR does not support unloading.
::FreeLibrary(m_coreCLRModule);
}
}
下面是判断TPA列表里面的项是否有包含文件,具体作用不详。
//TPA列表的每个项是否包含文件,至少有一项是包含文件的,那么返回TRUE
//fileNameWithoutExtension:不带后缀的文件名
//rgTPAExtensions:TPA后缀,注意这里是一个指针的指针。
//countExtensions:后缀个数
bool TPAListContainsFile(wchar_t* fileNameWithoutExtension, wchar_t** rgTPAExtensions, int countExtensions)
{
if (!m_tpaList.CStr()) return false;//如果程序集路径为空,直接返回FALSE //循环后缀。
for (int iExtension = 0; iExtension < countExtensions; iExtension++)
{
wchar_t fileName[MAX_LONGPATH];
// So that we don't match other files that end with the current file name
//不匹配其他文件结尾(和当前文件名对比)
wcscpy_s(fileName, MAX_LONGPATH, W("\\")); //wcscat_s函数,把第三个参数添加都第一个参数的结尾
wcscat_s(fileName, MAX_LONGPATH, fileNameWithoutExtension);
wcscat_s(fileName, MAX_LONGPATH, rgTPAExtensions[iExtension] + 1);
wcscat_s(fileName, MAX_LONGPATH, W(";")); // So that we don't match other files that begin with the current file name //类似于.NET中的Contains
if (wcsstr(m_tpaList.CStr(), fileName))
{
return true;
}
}
return false;
}
下面的方法是移除文件后缀的,应该是一个工具类
//移除文件后缀
void RemoveExtensionAndNi(wchar_t* fileName)
{
// Remove extension, if it exists
//如果文件存在后缀,那么久移除
wchar_t* extension = wcsrchr(fileName, W('.'));
if (extension != NULL)
{
extension[0] = W('\0'); // Check for .ni
//检测.ni文件,这种文件,我没在网上查到
size_t len = wcslen(fileName);
if (len > 3 &&
fileName[len - 1] == W('i') &&
fileName[len - 2] == W('n') &&
fileName[len - 3] == W('.') )
{
//结束字符,相当于.NET中的substring了
fileName[len - 3] = W('\0');
}
}
}
下面的2个方法都是加载文件到TpaList中。
// Returns the semicolon-separated list of paths to runtime dlls that are considered trusted.
// On first call, scans the coreclr directory for dlls and adds them all to the list. //返回可信任的且分号分隔的列表给运行时
//第一次CALL的时候,搜索coreclr目录里面的所有DLL,并把它们添加到TPAList中去
const wchar_t * GetTpaList() {
if (!m_tpaList.CStr()) { //文件后缀集合
wchar_t *rgTPAExtensions[] = {
// Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir
//如果是第一次加载 *.ni.dll文件,ni和il会有一个优先级的问题 W("*.ni.dll"),
W("*.dll"),
W("*.ni.exe"),
W("*.exe"),
}; // Add files from %CORE_LIBRARIES% if specified
//从%CORE_LIBRARIES%环境变量中加载文件,如果设定了此环境变量
wchar_t coreLibraries[MAX_LONGPATH];
size_t outSize;
if (_wgetenv_s(&outSize, coreLibraries, MAX_LONGPATH, W("CORE_LIBRARIES")) == 0 && outSize > 0)
{
wcscat_s(coreLibraries, MAX_LONGPATH, W("\\"));
AddFilesFromDirectoryToTPAList(coreLibraries, rgTPAExtensions, _countof(rgTPAExtensions));
}
else
{
*m_log << W("CORE_LIBRARIES not set; skipping") << Logger::endl;
*m_log << W("You can set the environment variable CORE_LIBRARIES to point to a") << Logger::endl;
*m_log << W("path containing additional platform assemblies,") << Logger::endl;
} //从目录中加载文件到TpaList中
AddFilesFromDirectoryToTPAList(m_coreCLRDirectoryPath, rgTPAExtensions, _countof(rgTPAExtensions));
} return m_tpaList.CStr(); //返回tpaList;
}
今天就说到这里了,下一篇跟大家预告一下,会 把GC的第三篇介绍写出来~~敬请期待哦~~~
C++随笔:.NET CoreCLR之corleCLR核心探索之coreconsole(2)的更多相关文章
- C++随笔:.NET CoreCLR之corleCLR核心探索之coreconsole(1)
一看这个标题,是不去取名有点绕呢?或者是,还有些问题?报告LZ...你的标题取得有问题,是个病句!↖(^ω^)↗!!!先不要急,其实我今天带给大家的就是CoreCLR中的coreclr.其中它是在名字 ...
- 【置顶】CoreCLR系列随笔
CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...
- 一系列令人敬畏的.NET核心库,工具,框架和软件
内容 一般 框架,库和工具 API 应用框架 应用模板 身份验证和授权 Blockchain 博特 构建自动化 捆绑和缩小 高速缓存 CMS 代码分析和指标 压缩 编译器,管道工和语言 加密 数据库 ...
- vNext之旅(1):从概念和基础开始
ASP.NET vNext or .NET vNext? vNext在曝光以来绝大多数以ASP.NET vNext这样的的字眼出现,为什么这边会提及.NET vNext?原因是我认为ASP.NET只是 ...
- ASP.NET vNext or .NET vNext?
ASP.NET vNext or .NET vNext? 从概念和基础开始 vNext在曝光以来绝大多数以ASP.NET vNext这样的的字眼出现,为什么这边会提及.NET vNext?原因是我认为 ...
- SQL-三级分类查询
/*SQLyog 企业版 - MySQL GUI v8.14 MySQL - 5.5.40 : Database - appinfodb******************************** ...
- mybatis第一天——入门与概述
大纲摘要: 1.mybatis的介绍 2.Mybatis的入门 a) 使用jdbc操作数据库存在的问题 b) Mybatis的架构 c) Mybatis的入门程序 3.Dao的开发方法 a) 原始da ...
- 基于SqlSugar的开发框架循序渐进介绍(3)-- 实现代码生成工具Database2Sharp的整合开发
我喜欢在一个项目开发模式成熟的时候,使用代码生成工具Database2Sharp来配套相关的代码生成,对于我介绍的基于SqlSugar的开发框架,从整体架构确定下来后,我就着手为它们量身定做相关的代码 ...
- C++随笔:.NET CoreCLR之GC探索(4)
今天继续来 带大家讲解CoreCLR之GC,首先我们继续看这个GCSample,这篇文章是上一篇文章的继续,如果有不清楚的,还请翻到我写的上一篇随笔.下面我们继续: // Initialize fre ...
随机推荐
- 懒加载session 无法打开 no session or session was closed 解决办法(完美解决)
首先说明一下,hibernate的延迟加载特性(lazy).所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作.因为hibernate当中支持实体对象,外键会与实体对象关联起来.如 ...
- C++中的时间函数
C++获取时间函数众多,何时该用什么函数,拿到的是什么时间?该怎么用?很多人都会混淆. 本文是本人经历了几款游戏客户端和服务器开发后,对游戏中时间获取的一点总结. 最早学习游戏客户端时,为了获取最精确 ...
- 【原】AFNetworking源码阅读(一)
[原]AFNetworking源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 AFNetworking版本:3.0.4 由于我平常并没有经常使用AFNetw ...
- 创建 OVS Local Network - 每天5分钟玩转 OpenStack(129)
上一节我们完成了 OVS 的准备工作,本节从最基础的 local network 开始学习.local network 不会与宿主机的任何物理网卡连接,流量只被限制在宿主机内,同时也不关联任何的 VL ...
- python与c互相调用
虽然python开发效率很高,但作为脚本语言,其性能不高,所以为了兼顾开发效率和性能,通常把性能要求高的模块用c或c++来实现或者在c或c++中运行python脚本来处理逻辑,前者通常是python中 ...
- Oracle 数据库知识汇总篇
Oracle 数据库知识汇总篇(更新中..) 1.安装部署篇 2.管理维护篇 3.数据迁移篇 4.故障处理篇 5.性能调优篇 6.SQL PL/SQL篇 7.考试认证篇 8.原理体系篇 9.架构设计篇 ...
- java单向加密算法小结(1)--Base64算法
从这一篇起整理一下常见的加密算法以及在java中使用的demo,首先从最简单的开始. 简单了解 Base64严格来说并不是一种加密算法,而是一种编码/解码的实现方式. 我们都知道,数据在计算机网络之间 ...
- ActiveRecord模式整理
DAO Data Access Object,数据访问对象 DAO是一个软件设计的指导原则,在核心J2EE模式中是这样介绍DAO模式的:为了建立一个健壮的J2EE应用,应该将所有对数据源的访问操作抽象 ...
- RSA算法
RSA.h #ifndef _RSA_H #define _RSA_H #include<stdio.h> #include<iostream> #include<mat ...
- 初识JavaScript
JavaScript ECMA-262: 变量,函数,对象,数据类型....唯独没有输入和输出. Javascript:包含 ECMA-262,核心 BOM 浏览器对象模型, DOM 文档对象模型 什 ...