zoukankan      html  css  js  c++  java
  • 运行机制---进阶编程篇(一)

           我已经假定你安装了宇宙第一IDE:visual studio 2017版本了,一个好的IDE会让你在敲代码的时候获得一个好心情,想想多年以前,很多人还是用VC++6.0,估计在现在,还是有一部分的人在使用,那个IDE用起来非常的不顺手,连提示错误都没有,很多时候我们只是手贱打错了个字,为了查错那个辛苦啊。扯远了,反正我没用过VC++6.0,如果你开始使用,推荐也是从最新版开始吧。

          我们开始新建第一个winform项目,点击新建项目后就弹出来下面的对话框:

          

    新建完成后,就是如下的界面了:

          

    这时候点击F5运行,然后就是这样:

          

          此处就出现了一个窗体,操作熟练的话,整个过程不到5秒就创建成功一个窗体了,一切都是那么的自然,自然的让我们以为创建窗口就应该是这个样子的,简单,高效,不得不说,这也是微软这么多年来努力的目标之一,就是让大家在开发程序的时候,可以尽可能的快速,便捷式操作,傻瓜式操作,使得编程的门槛大幅度的降低,上述的操作交给一个完全的新手时,几分钟就教会了。然后教教他怎么显示文本,怎么改变文本,估计也是几分钟的事情,就可以写一个简单的程序了。微软这么做的结果就是降低编程门槛,越来越多的人来学习C#,但也导致了水平普遍偏低的结果,就比如创建这个窗口,你在创建一百个这样的窗口,水平也没有提升再多了,因为这简单的几部它就是没什么技术含量的。

          终于进入到了本文的重点了,讲解我们用C#编写的程序的运行机制,这部分的内容对于新人来讲确实挺难理解的,我一开始学习的时候简直就是看天书一样的,所以我会尽量的将我所知道的用平实的语言讲出来,这部分内容对于理解C#来说至关重要,也是进阶的必经之路。所以我先大概说明一下运行机制,再分部完成。

      就比如上面生成的exe程序,它到底是什么玩意,我想很多人都会疑问,刚学习C#的我也是这样。

    1. 我们首先在VS中写了很多的代码,点击生成或是调试的时候,IDE使用了C#编译器将我们写的所有的代码编译成了一种中间语言IL语言,写入到了生成的exe中。
    2. 可以想想看exe包含了什么东西,我们在上述的项目中定义了新的类Form1,那么这些类系统又不提供,所以肯定会把类写入到exe中,只要是自定义的类肯定会写入进去。
    3. 我们可以猜测exe文件应该还有个文件头,来标识这是一个可执行的Win32程序,我们在创建项目时可以选择.NET版本,应该还包含了环境版本

      到这里我们的猜测已经非常的接近事实的情况了, 所以当我们点击exe程序的时候,windows到底干了什么东西。

      

      首先windows会检查exe文件的文件头,检查程序类型是不是PE32文件头还是PE32+文件头的,这个文件头要求程序的运行环境,是不是32位,还是64位的,如果和操作系统不匹配,则不会运行,检查.NET 的版本号。

      windows检查完exe后,检查合格后,接下来就要创建程序需要运行的进程空间了,在进程的地址空间加载MSCorEE.dll(一个.NET framework自带的链接库,可以在安装目录找到)。

      MSCorEE.dll的用处非常大,进程的主线程会调用组件的方法来初始化运行的CLR,然后加载exe的数据(就是中间语言IL代码,包含了所有的类型说明和数据,即使加载了,还是IL代码,还不不能直接运行的,如果你的exe还引用了其他的dll,那么所有的关联的dll都会加载进来)。

      然后MSCorEE.dll组件调用Main方法,这个和我们大学学的C语言是一致的,但是问题出现了,我们上面说过这时候CLR加载的还是IL代码,IL代码又不能直接运行,所以CLR内部的JITCompiler方法就出来干活了,工作是将IL代码编译成本机的CPU指令,这样操作后Main方法才可以真正的运行,如果Main方法调用了其他方法(这不是废话么),那么JITCompiler又出来工作了,如果每次调用方法,都要重新编译一次,那么应用程序的性能就非常差了,所以CLR使用了缓存的机制,所有的方法只有在第一次调用的时候存在一点性能损耗,以后调用就直接使用了本地指令。

      绕着这么多的弯路,终于窗体运行了,展示给你看了,汗颜-------

      这里肯定会有小伙伴跳出来说,这么搞累不累啊,我也想说,确实挺累的,为了运行一个程序,绕了一个大弯,我还记得我在大学的时候学的单片机,虽然我使用C语言来写程序的,但是编译器直接编译成了汇编写入ROM中,然后指针就可以直接调用程序了,你看,多么的简单明了。相比较而言,我们就不能用C#写的程序生成windows直接可以运行的程序吗?或者说直接生成IL的exe,再编译一次直接生成机器语言多好,运行效率会高很多。

      要想回答这个问题,我们需要探究一下IL语言为什么会产生,大致就能回答上述的问题了,说到IL的产生,又不得不说.NET的生成历史,当年微软看到JAVA发展如你中天时,心里也痒痒了,也想做一个新的语言,运行在虚拟机上,这样的程序和平台无关,可以实现程序的方便移植,虽然后来做着做着还是绑定了windows系统,但是至少和windows版本没有了太大的关系,比如上述的exe程序,是基于.NET 4.5的,只要安装了.NET 4.5的话就可以很好的支持,不必为了针对哪个系统,哪个CPU架构来区别对待。事实上基于CLR的IL可以实现的功能非常的强大,拥有完整的面向对象的机制,提供了抛出异常和处理模型,只是在C#层面就只能实现部分的CLR功能,也就是说,如果CLR不支持的功能,在C#层面就肯定不支持了。

      如果直接生成了基于机器指令的exe程序,事实上微软完全可以做到,但是这也丧失了动态性能,JITCompiler在即时编译指令时,会根据当前的cpu来优化本地指令,为特定cpu生成的程序有可能会在其他电脑无法运行,这就失去了程序的健壮性,谁都不会希望开发出这种程序吧。

      关于性能损耗,微软早就意识到这个问题了,花了非常大的人力物力来优化JIT的性能损耗,在我的经验中,性能非常的高效,已经满足绝大多数的场景。

      到此处为此,其实已经说的非常完整了,需要多读几遍,才能比较好的理解,也可以自己去查查看IL代码是什么样子的,相信还有很大的收获的。

  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/dathlin/p/7213793.html
Copyright © 2011-2022 走看看