挡不住的好奇心:ASP.NET 5是如何通过XRE实现跨平台的

 

.NET程序员也有自己的幸福,.NET的跨平台是一种幸福,.NET的开源也是一种幸福,而更幸福的是可以通过开源的.NET了解.NET是如何一步步走向跨平台的,所以幸福是一种过程。

在.NET跨平台的进程中,ASP.NET显然走在了前头,而通过探究ASP.NET 5是如何实现跨平台的,可以稍稍满足一下自己的好奇心。

体验ASP.NET 5跨平台有2种方式:

1)在Mac下,git签出XRE的源代码(前身是KRuntime),然后运行sh build.sh,就能完成整个XRE项目的生成。

2)在Mac下,写一个简单的ASP.NET项目,然后用k kestrel运行,详见不写1行代码,在Mac上体验ASP.NET 5的最简单方法

这篇博文就从k命令下手,一探ASP.NET 5跨平台的究竟。

运行k kestrel(即将是dotnet kestrel),实际运行的是下面的命令(根据project.json中的commands配置):

k "Microsoft.AspNet.Hosting --server kestrel --server.urls http://localhost:8002"

Microsoft.AspNet.Hosting是一个.NET控制台程序实现的OWIN Host(源码),kestrel是一个基于libuv用.NET实现的OWIN Server(也是Web Server,源码),kestel是由Microsoft.AspNet.Hosting加载的。

既然Microsoft.AspNet.Hosting是一个托管程序,它自己是无法直接运行的。因为运行一个.NET程序的前提条件是CLR已运行,而CLR自己不能运行自己,CLR运行的前提是有一个host程序将它加载。

如果你在Mac下用过Mono,就你就知道运行一个.NET程序需要用mono命令,mono命令的作用就是创建一个进程,加载Mono Runtime(Mono CLR),然后由Mono Runtime执行.NET程序。

而在ASP.NET 5中,并没有直接用mono命令,而是k命令,自从KRuntime改名为XRE之后,k命令也将会被dotnet命令取代。

在非Windows平台下,k命令对应的是k.sh。现在改为XRE之后,也就是donet命令对应dotnet.sh。所以ASP.NET 5跨平台的秘密就藏在dotnet.sh中。

下面就直击XRE项目中的scripts/dotnet.sh:

#...
if [ -f "$DIR/mono" ]; then
exec "$DIR/mono" $MONO_OPTIONS "$DIR/dotnet.mono.managed.dll" "$@"
else
exec mono $MONO_OPTIONS "$DIR/dotnet.mono.managed.dll" "$@"
fi

毫无悬念,依然用的是mono。但是用了mono,如何加载.NET Core CLR,难道还是用Mono Runtime?

带着这个疑问,顺藤摸瓜,看dotnet.mono.managed.dll干了啥。

dotnet.mono.managed.dll的实现代码就在XRE项目中,是一个简单的C#控制台程序,它干了两件事:1)分析命令行参数;2)调用RuntimeBootstrapper.Execute():

public class EntryPoint
{
public static int Main(string[] arguments)
{
//...
arguments = ExpandCommandLineArguments(arguments);
//...
return RuntimeBootstrapper.Execute(arguments);
}
}

继续顺藤摸瓜至 [dotnet.hosting.RuntimeBootstrapper],[RuntimeBootstrapper.Execute()] 调用了 [RuntimeBootstrapper.ExecuteAsync()]。

而托管的 [RuntimeBootstrapper.ExecuteAsync()] 竟然拐了个弯,执行了非托管的dotnet命令(一个由dotnet.cpp实现的C++程序)。

mono命令(非托管) -> Mono Runtime -> dotnet.mono.managed(托管) -> RuntimeBootstrapper(托管) -> dotnet命令(非托管),ASP.NET 5 XRE的代码真是十八弯。

千呼万唤始出来,原来真正的主角就藏在十八弯之后。

dotnet.cpp加载了非托管的dotnet.coreclr.dll:

LPCWSTR pwzHostModuleName = L"dotnet.coreclr.dll";
m_hHostModule = ::LoadLibraryExW(pwzHostModuleName, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
pfnCallApplicationMain = (FnCallApplicationMain)::GetProcAddress(m_hHostModule, pszCallApplicationMainName);

而dotnet.coreclr.dll是由XRE中的C++程序dotnet.coreclr.cpp实现的,最终由dotnet.coreclr.cpp加载了coreclr.dll:

hCoreCLRModule = ::LoadLibraryExW(L"coreclr.dll", NULL, 0);

dotnet.coreclr.cpp就是加载CLR的主角。

这不让人产生疑问,这也可以?仅靠一个C++程序就能加载CLR,执行.NET程序,那我们在Windows上为什么要安装一个庞大的.NET Framework?

真的可以!一个非托管的host程序+CLR,就能运行.NET程序,不信你可以看这篇文章震撼一下:Hosting .NET Core Clr in your own process 。

加载CLR的目的是为了执行.NET程序集中的IL代码,而要执行的程序集是由dotnet命令(前身是k命令)的命令行参数所传递过来的,比如dotnet kestrel(之前是k kestrel),对应的程序集是 Microsoft.AspNet.Hosting。CLR调用 Microsoft.AspNet.Hosting.Program.Main() 方法开始执行,ASP.NET 5就开始干活了。

Core CLR被加载、Microsoft.AspNet.Hosting被运行之后,在 RuntimeBootstrapper.ExecuteAsync() 中,还继续加载了一些dotnet.host的相关程序集(注意:这时不是Core CLR,而是Mono Runtime)。

//...
var assembly = Assembly.Load(new AssemblyName("dotnet.host"));
//...
var loaderContainerType = assembly.GetType("dotnet.host.LoaderContainer");
var cachedAssemblyLoaderType = assembly.GetType("dotnet.host.CachedAssemblyLoader");
var pathBasedLoaderType = assembly.GetType("dotnet.host.PathBasedAssemblyLoader");
//...

到这里,不知你有没有被这十八弯给绕晕,如果没被绕晕,请继续往下看。

这时一个大大的问号浮现在眼前,既然dotnet命令能直接加载Core CLR,为什么还要用mono命令中转一下?

百思不得其解。。。

在写这篇博文的过程中,突然产生了一个大胆猜想——

在Core CLR被加载,Microsoft.AspNet.Hosting被执行之后,为什么还要用Mono Runtime加载一些dotnet.host相关的程序集?为什么不直接用Core CLR加载呢?这只能用一个原因来解释,dotnet.host依赖的一些程序集在在.NET Framework中有实现,但是在.NET Core Framework中还没有实现,而Mono是.NET Framework的一个跨平台实现,在Mono中也有对应的实现。完整的.NET Core Framework(github.com/dotnet/corefx)还在紧张开发之中,在它出来之前,微软只能借助Mono。这也是ASP.NET的跨平台走在前面要付出的代价,随着.NET Core Framework的完成,XRE的改进,可以预计ASP.NET的跨平台是会脱离Mono的。

当然,这只是一个猜想,如果你知道真相,欢迎来揭开。

 
 
标签: DotNetCoreASP.NET5XRE

ASP.NET 5是如何通过XRE实现跨平台的的更多相关文章

  1. 挡不住的好奇心:ASP.NET 5是如何通过XRE实现跨平台的

    .NET程序员也有自己的幸福,.NET的跨平台是一种幸福,.NET的开源也是一种幸福,而更幸福的是可以通过开源的.NET了解.NET是如何一步步走向跨平台的,所以幸福是一种过程. 在.NET跨平台的进 ...

  2. .NET:从 Mono、.NET Core 说起

    魅力 .NET:从 Mono..NET Core 说起 前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基 ...

  3. 魅力 .NET:从 Mono、.NET Core[转]

    前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 .NET 程序员最基本的...呵呵! 微软开源,其实不只是对 .NET 本身 ...

  4. ASP.NET Core 介绍

    原文:Introduction to ASP.NET Core 作者:Daniel Roth.Rick Anderson.Shaun Luttin 翻译:江振宇(Kerry Jiang) 校对:许登洋 ...

  5. .NET跨平台之旅:生产环境中第2个跑在Linux上的ASP.NET Core站点

    今天我们在生产环境中上线了第2个跑在Linux上的ASP.NET Core站点.这是一个简单的Web API站点,通过命令行的方式调用安装在Linux服务器上的程序完成操作.之前用的是nodejs,现 ...

  6. 跨平台运行ASP.NET Core 1.0

    前言 首先提一下微软更名后的叫法: ASP.NET 5 更名为 ASP.NET Core 1.0 .NET Core 更名为 .NET Core 1.0 Entity Framework 7 更名为  ...

  7. .NET跨平台之旅:借助ASP.NET 5 Beta5的新特性显示CLR与操作系统信息

    今天在 MSDN 博客上看到了 ASP.NET 5 Beta5 的发布消息(详见 ASP.NET 5 Beta5 Now Available),从中知道了 2 个新特性: 1. DNX: New IR ...

  8. 从一个简单的ASP.NET 5站点开启.NET跨平台之旅

    在经历了阿里云上“黑色1秒”的空欢喜之后,我们“被迫”考虑实现.NET的跨平台,将Web服务器由Windows换成Linux.而这种“被迫”在一个存在已久的愿望下,变得水到渠成.这个愿望就是 —— “ ...

  9. ASP.net Core部署说明(Ubuntu) [转]

    最近在学习asp.net core,当然学习的目的是想了解一下,Asp.net core是否真的能够是先跨平台部署. 根据目前官网资料说明,asp.net core只有在Redhat 企业版上,才能够 ...

随机推荐

  1. BZOJ 2435 NOI2011 道路建设 BFS/DFS

    标题效果:给定一个树(直接将树.不要贪图生成树图!).寻找每条边权值*分差的两侧之间 BFS水必须是能 竟DFS能够住...系统堆栈可能有些不够,我们可以使用内联汇编手册中大型系统堆栈 详见代码 这个 ...

  2. 容易centos配置docker维修

    首先.由于docker实施需要linux某些组件支持本身和内核特性.所以一定要确保centos版本号大于6,和内核版本号大于2.6.32-431.可轻松升级centos6到最新的版本号. sudo y ...

  3. POJ2195 Going Home 【最小费用流】+【最佳匹配图二部】

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18169   Accepted: 9268 Descr ...

  4. 巧妙设备MTU的大小,轻松提网速

    MTU是什么? "MTU=最大传输单元 单位:字节" 我们在使用互联网时进行的各种网络操作,都是通过一个又一个"数据包"传输来实现的.而MTU指定了网络中可数据 ...

  5. IT该忍者神龟Jquery小工具easyUI物业摘要召回

    找了个时间看了下EasyUI插件.对它的插件感觉是非常舒服,特地把Easy UI的大部分功能属性做了一下汇总. 此属性列表请对比jQuery EasyUI 1.0.5,关于它的很多其它资讯请猛击这里. ...

  6. 读改善c#代码157个建议:建议7~9

    目录: 建议7:将0值作为枚举的默认值 建议8:避免给枚举类型的元素提供显示的值 建议9:习惯运算符重载 一.建议7:将0值作为枚举的默认值 允许使用的枚举类型有:byte.sbyte.short.u ...

  7. TCP/IP、Http、Socket的差别

    网络由下往上分为 物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 通过初步的了解,我知道IP协议相应于网络层,TCP协议相应于传输层,而HTTP协议相应于应用层, 三者从本质上来说没有可 ...

  8. 【cocos2d-js公文】十八、Cocos2d-JS v3.0物业风格API

    1. 新的API风格 我们直接来看看你能够怎样使用Cocos2d-JS v3.0: 曾经的API 新的API node.setPosition(x, y); node.x = x; node.y = ...

  9. vs2013 ADO联系SQL server2012数据库

    平时,给定ADO例如使用以下过程数据源中的数据的数据库应用程序 (1) 创建一个Connection 物.定义的连接字符串信息.它包含了数据源名称.用户ID.密码.连接超时 . 默认数据库的位置和光标 ...

  10. 华为-on练习--重复的字符过滤

    称号: 请写一个字符串过滤程序,如果使用多个相同的字符出现在字符串中,字符首次出现在非过滤,. 比方字符串"abacacde"过滤结果为"abcde". 演示样 ...