前言

.Net运行模型,无非就两个过程。一个是调用入口函数,另外一个就是编译入口函数。前者主调用,后者主编译。

概括

一:入口函数:RunMainInternal

所有的.Net程序,包括控制台,Web,窗体等等入口都是Main。而调用这个Main的就是RunMainInternal,从这个函数的名字就可以看出,它的Run就表示是运行Main函数的,而后面的Internal表示是内部的,而非外部所能调用,当然你用一些非常规手段,这个函数还是可以外部的调用的,那是后话。

二:通过LLDB看下它的堆栈

* thread #1, name = 'corerun', stop reason = step over
* frame #0: 0x00007ffff6d53cdf libcoreclr.so`RunMainInternal
frame #1: 0x00007ffff6d53c99 libcoreclr.so`RunMain
frame #2: 0x00007ffff6d4ec76 libcoreclr.so`RunMain
frame #3: 0x00007ffff6d4ea22 libcoreclr.so`RunMain
frame #4: 0x00007ffff6d4f030 libcoreclr.so`Assembly::ExecuteMainMethod
frame #5: 0x00007ffff6dc2b9c libcoreclr.so`CorHost2::ExecuteAssembly
frame #6: 0x00007ffff6d1a6c1 libcoreclr.so`::coreclr_execute_assembly
frame #7: 0x000055555556f9f9 corerun`run(config=0x00007fffffffdbc0)
frame #9: 0x00007ffff7829d90 libc.so.6`__libc_start_call_main
frame #10: 0x00007ffff7829e40 libc.so.6`__libc_start_main_impl
frame #11: 0x000055555556c0e5 corerun`_start + 37

可以看到它在Linux平台下面,是通过Glibc OR Newlibc调用的。而它的前面一个函数就是RunMain,这个通过它名字也可以看到它就是运行Main函数的。

三:编译函数PreStubWorker

这个函数顾名思义,预桩工作。就是插桩的意思。每次编译一个函数,都会经过它。它会调用RyuJIT把函数编译成机器码,然后再返回到这个被编译函数的函数头地址运行。

部分代码:

extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, MethodDesc* pMD)
{
PCODE pbRetVal = NULL; BEGIN_PRESERVE_LAST_ERROR; STATIC_CONTRACT_THROWS;
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_MODE_ANY;
STATIC_CONTRACT_ENTRY_POINT;
// 此处省略一万字
}

可以看到它只是带了一个MethodDesc,也就是函数的描述结构体。通过它可以找到Module,MSIL,然后进行一个编译。

四:看下它的堆栈

 thread #1, name = 'corerun', stop reason = breakpoint 2.1
* frame #0: 0x00007ffff6ef55d0 libcoreclr.so`::PreStubWorker
frame #2: 0x00007ffff731e14f libcoreclr.so`CallDescrWorkerInternal
frame #3: 0x00007ffff6faae98 libcoreclr.so`CallDescrWorkerWithHandler
frame #4: 0x00007ffff6fabb8d libcoreclr.so`MethodDescCallSite::CallTargetWorker
frame #5: 0x00007ffff6d2e4b3 libcoreclr.so`MethodDescCallSite::Call
frame #6: 0x00007ffff6d53f6f libcoreclr.so`RunMainInternal
frame #7: 0x00007ffff6d53c99 libcoreclr.so`RunMain
frame #8: 0x00007ffff6d4ec76 libcoreclr.so`RunMain
frame #9: 0x00007ffff6d4ea22 libcoreclr.so`RunMain
frame #10: 0x00007ffff6d4f030 libcoreclr.so`Assembly::ExecuteMainMethod
frame #11: 0x00007ffff6dc2b9c libcoreclr.so`CorHost2::ExecuteAssembly
frame #12: 0x00007ffff6d1a6c1 libcoreclr.so`::coreclr_execute_assembly
frame #13: 0x000055555556f9f9 corerun`run(config=0x00007fffffffdbc0) argv=0x00007fffffffddb8) at corerun.cpp:624:21
frame #15: 0x00007ffff7829d90 libc.so.6`__libc_start_call_main
frame #16: 0x00007ffff7829e40 libc.so.6`__libc_start_main_impl
frame #17: 0x000055555556c0e5 corerun`_start + 37

它刚好在RunMainInternal的后面,说明它是在被调用之后,才会进行编译。

结尾

作者:江湖评谈

.Net7 CLR的调用函数和编译函数的更多相关文章

  1. C++调用C中编译过的函数要加extern "C"

    C++语言支持函数重载,C语言不支持函数重载.函数被C++编译后在库中的名字与C语言的不同.假设某个C 函数的声明如下:void foo(int x, int y);该函数被C 编译器编译后在库中的名 ...

  2. C/C++:函数的编译方式与调用约定以及extern “C”的使用

    转自:https://www.cnblogs.com/qinfengxiaoyue/archive/2013/02/04/2891908.html 函数在C++编译方式与C编译方式下的主要不同在于:由 ...

  3. 【原创】Matlab.NET混合编程技巧之直接调用Matlab内置函数

                  本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新    Matlab和C#混合编程文章目录 :[目录]Matlab和C#混合编程文章目录 在我的上一篇文章[ ...

  4. Matlab.NET混合编程技巧之——直接调用Matlab内置函数(附源码)

    原文:[原创]Matlab.NET混合编程技巧之--直接调用Matlab内置函数(附源码) 在我的上一篇文章[原创]Matlab.NET混编技巧之——找出Matlab内置函数中,已经大概的介绍了mat ...

  5. jQuery 2.0.3 源码分析Sizzle引擎 - 编译函数(大篇幅)

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 从Sizzle1.8开始,这是Sizzle的分界线了,引入了编译函数机制 网上基本没有资料细说这个东东的,sizzle引入这 ...

  6. mfc 调用Windows的API函数实现同步异步串口通信(源码)

    在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...

  7. 在VS2012中采用C++中调用DLL中的函数 (4)

    这两天因为需要用到VS2012来生成一个DLL代码,但是之前并没有用过DLL相关的内容,从昨天开始尝试调试DLL的文件调用,起初笔者在网络上找到了3片采用VSXXX版本进行调试的例子,相关的内容见本人 ...

  8. 在C++中调用DLL中的函数 (3)

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  9. 在C++中调用DLL中的函数 (2)

    应用程序使用DLL可以采用两种方式: 一种是隐式链接,另一种是显式链接.在使用DLL之前首先要知道DLL中函数的结构信息. Visual C++6.0在VC\bin目录下提供了一个名为Dumpbin. ...

  10. 在C++中调用DLL中的函数

    如何在C++中调用DLL中的函数 应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接.在使用DLL之前首先要知道DLL中函数的结构信息.Visual C++6.0在VC\bin目录下 ...

随机推荐

  1. HCIP-ICT实战进阶04-ISIS原理与配置

    HCIP-ICT实战进阶04-ISIS原理与配置 0 前言 IS-IS(Intermediate System to Intermediate System, 中间系统到中间系统)协议, 和OSPF一 ...

  2. 记录一次echarts 中bar 定时跳跃并显示内容

    查看echarts api -----   https://www.echartsjs.com/zh/api.html#echarts 搜索 1.dispatchAction   执行的关键 2.hi ...

  3. 保护IIS Web服务器安全的技巧

    首先,开发一套安全策略 保护Web服务器的第一步是确保网络管理员清楚安全策略中的每一项制度.如果公司高层没有把服务器的安全看作是必须被保护的资产,那么保护工作是完全没有意义的.这项工作需要长期的努力. ...

  4. 第一课 Markdown 实操

    1.Markdown (#加空格) 二级标题 (##加空格) 三级标题 (###加空格) 四级标题 (####加空格) 2.字体 Hello world 加粗(字体2边加**) Hello world ...

  5. CH32F103C8T6的USB开发(一)

    一.背景 项目用到单片机采集模拟量数据,原先使用USB转串口,速度嫌慢,还要转串口芯片,电脑还要安装驱动,现更改为采用USB的HID类来传输. 二.单片机选型 STM32F103的USB接口简单易用, ...

  6. 【Android异常】关于静态注册BroadcastReceiver接收不到系统广播的问题

    如果你静态注册的广播无法接收到消息,请先检查下:你的安卓版本是不是8.0+ 前言Google官方声明:Beginning with Android 8.0 (API level 26), the sy ...

  7. 使用python-docx提取word中的表格

    提取表格 import docx from docx import Document #导入库 path = '123.docx' #文件路径 document = Document(path) #读 ...

  8. Educational Codeforces Round 2 个人总结A-E

    Educational Codeforces Round 2 A. Extract Numbers 简单的模拟 bool check(string op) { if(op.size()==1& ...

  9. C#MSDN简体中文 最后一版本 2007年的

    我在学习C# 需要 先看 MSDN文档,英文看的很吃力,就找了好久 MSDN简体中文版本的: 因为微软已经关闭网站(MSDN中文的链接),我找到的就是  磁力链接的: 我分享出来 ,有需要的 自行下载 ...

  10. centos7 redis 无法用 systemctl 启动

    今天刚安装了redis,修改了 /etc/redis.conf 的内容. 尝试在 bind 后添加一个地址 "bind 127.0.0.1 -::* 192.168.2.1", 后 ...