欢迎光临
我们一直在努力

ASP.NET底层架构探索之进入.NET运行时-.NET教程,Asp.Net开发

建站超值云服务器,限时71元/月

进入.net运行时的真正的入口发生在一些没有被文档记载的类和接口中(译著:当然,你可以用reflector来查看j).除了微软,很少人知道这些接口,微软的家伙们也并不热衷于谈论这些细节,他们认为这些实现细节对于使用asp.net开发应用的开发人员并没有什么用处。

  工作进程(iis5中是aspnet_wp.exe,iis6中是w3wp.exe)寄宿.net运行时和isapi dll,它(工作进程)通过调用com对象的一个小的非托管接口最终将调用发送到isapiruntime类的一个实例上(译注:原文为an instance subclass of the isapiruntime class,但是isapiruntime类是一个sealed类,疑为作者笔误,或者这里的subclass并不是子类的意思).进入运行时的第一个入口就是这个没有被文档记载的类,这个类实现了iisapiruntime接口(对于调用者说明来说,这个接口是一个com接口)这个基于iunknown的底层com接口是从isapi扩展到asp.net的一个预定的接口.图3展示了iisapiruntime接口和它的调用签名.(使用了lutz roeder出色的.net reflector 工具http://www.aisto.com/roeder/dotnet/).这是一个探索这个步步为营过程的很好的方法.

  

  图3-如果你想深入这个接口,打开reflector,指向system.web.hosting命名空间. isapi dll通过调用一个托管的com接口来打开进入asp.net的入口,asp.net接收一个指向isapi ecb的非托管指针.这个ecb包含访问完整的isapi接口的能力,用来接收请求和发送响应回到iis.

  iisapiruntime接口作为从isapi扩展来的非托管代码和asp.net之间的接口点(iis6中直接相接,iis5中通过命名管道).如果你看一下这个类的内部,你会找到含有以下签名的processrequest函数:

  [return: marshalas(unmanagedtype.i4)]

  int processrequest([in] intptr ecb,

  [in, marshalas(unmanagedtype.i4)] int useprocessmodel);

  其中的ecb参数就是isapi扩展控制块(extention control block),被当作一个非托管资源传递给processrequest函数.这个函数接过ecb后就把它做为基本的输入输出接口,和request和response对象一起使用.isapi ecb包含有所有底层的请求信息,如服务器变量,用于表单(form)变量的输入流和用于回写数据到客户端的输出流.这一个ecb引用基本上提供了用来访问isapi请求所能访问的资源的全部功能,processrequest是这个资源(ecb)最初接触到托管代码的入口和出口.

  isapi扩展异步地处理请求.在这个模式下isapi扩展马上将调用返回到工作进程或者iis线程上,但是在当前请求的生命周期上ecb会保持可用.ecb含有使isapi知道请求已经被处理完的机制(通过ecb.serversupportfunction方法)(译注:更多信息,可以参考开发isapi扩展的文章),这使得ecb被释放.这个异步的处理方法可以马上释放isapi工作线程,并将处理传递到由asp.net管理的一个单独的线程上.

  asp.net接收到ecb引用并在内部使用它来接收当前请求的信息,如服务器变量,post的数据,同样它也返回信息给服务器.ecb在请求完成前或超时时间到之前都保持可访问(stay alive),这样asp.net就可以继续和它通讯直到请求处理完成.输出被写入isapi输出流(使用ecb.writeclient())然后请求就完成了,isapi扩展得到请求处理完成的通知并释放ecb.这个实现是非常高效的,因为.net类本质上只是对高效的、非托管的isapi ecb的一个非常”瘦”(thin)的包装器.

  装载.net-有点神秘

  让我们从这儿往回退一步:我跳过了.net运行时是怎么被载入的.这是事情变得有一点模糊的地方.我没有在这个过程中找到任何的文档,而且因为我们在讨论本机代码,没有很好的办法来反编译isapi dll并找出它(装载.net运行时的代码)来.

  我能作出的最好的猜测是当isapi扩展接受到第一个映射到asp.net的扩展名的请求时,工作进程装载了.net运行时.一旦运行时存在,非托管代码就可以为指定的虚拟目录请求一个isapiruntime的实例(如果这个实例还不存在的话).每个虚拟目录拥有它自己的应用程序域(appdomain),当一个独立的应用(指一个asp.net程序)开始的时候isapiruntime从启动过程就一直在应用程序域中存在.实例化(译注:应该是指isapiruntime的实例化)似乎是通过com来进行的,因为接口方法都被暴露为com可调用的方法.

  当第一个针对某虚拟目录的请求到来时,system.web.hosting.appdomainfactory.create()函数被调用来创建一个isapiruntime的实例.这就开始了这个应用的启动进程.这个调用接收这个应用的类型,模块名称和虚拟目录信息,这些信息被asp.net用来创建应用程序域并启动此虚拟目录的asp.net程序.这个httpruntime实例(译注:原文为this httpruntime derived object,但httpruntime是一个sealed类,疑为原文错误)在一个新的应用程序域中被创建.每个虚拟目录(即一个asp.net应用程序寄)宿在一个独立的应用程序域中,而且他们也只有在特定的asp.net程序被请求到的时候才会被载入.isapi扩展管理这些httpruntime对象的实例,并根据请求的虚拟目录将内部的请求路由到正确的那个httpruntime对象上.

  

  图4-isapi请求使用一些没有文档记载的类,接口并调用许多工厂方法传送到asp.net的http管道的过程.每个web程序/虚拟目录在它自己的应用程序域中运行,调用者(译注:指isapi dll)保持一个iisapiruntime接口的引用来触发asp.net的请求处理.

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » ASP.NET底层架构探索之进入.NET运行时-.NET教程,Asp.Net开发
分享到: 更多 (0)