当前位置: 首页 > news >正文

做视频网站要多大的带宽做网站双12促销方案

做视频网站要多大的带宽,做网站双12促销方案,印发网站建设方案,永年网站建设在上一篇博客是使用官方提供的 AppHost 跑起来整个 dotnet 程序。本文告诉大家在 dotnet 程序运行到托管代码之前#xff0c;所需要的 Native 部分的逻辑。包括如何寻找 dotnet 运行时#xff0c;如何加载运行时和框架然后跑起来业务端的 dll 文件的逻辑在上一篇博客告诉大家… 在上一篇博客是使用官方提供的 AppHost 跑起来整个 dotnet 程序。本文告诉大家在 dotnet 程序运行到托管代码之前所需要的 Native 部分的逻辑。包括如何寻找 dotnet 运行时如何加载运行时和框架然后跑起来业务端的 dll 文件的逻辑在上一篇博客告诉大家在 dotnet 的 AppHost 是如何做的详细请看 dotnet core 应用是如何跑起来的 通过AppHost理解运行过程那如果我想要定制运行时的寻找路径呢在 dotnet core 应用是如何跑起来的 通过AppHost理解运行过程 只是告诉大家如何定制咱的业务端的 dll 寻找路径阅读本文能收获了解 dotnet 的执行引擎实际没有执行引擎这个概念是如何被启动的学会一个黑科技自定义运行时所在的文件夹了解为什么 dotnet core 和 dotnet framework 不一样不需要依赖环境安装了框架在开始之前需要了解什么是 dotnet host 这个概念。在运行 dotnet 程序的时候在 windows 下需要通过 win32 的形式运行。而大家都知道如果不开 AOT 等黑科技咱构建输出的 dll 是 IL 中间格式的但是可执行程序是只认机器码汇编的。如何从咱的 IL 逻辑到机器运行呢今天咱来写这部分的逻辑让整个 dotnet 跑起来的启动部分需要知道整个 dotnet 的启动机制是特别复杂的本文只是告诉大家如何跑起来也就是只是调用各个方法而已细节部分我就不敢讲了在 dotnet 里面需要先启动动态编译模块而动态即时编译模块的启动运行部分非全部本质上是一个被构建为本机代码的一个模块需要被 Native 的逻辑执行。而运行时本身需要在 dotnet 的托管代码执行之前热起来运行时的启动部分代码也是一个被构建为本机代码的模块那在咱双击一个 dotnet 应用构建出来的 exe 时到底发生了什么咱双击的这个 dotnet 应用构建出来的 exe 本质上是一个从模版创建的二进制文件这是一个原本由纯 Native 构成的模版二进制文件在咱构建 dotnet 的过程被复制到咱的输出路径然后通过替换二进制文件里面的占坑部分内容完成这个二进制文件。这部分细节请看 dotnet core 应用是如何跑起来的 通过AppHost理解运行过程而下面咱将不使用模版文件创建 dotnet 的可执行文件而是自己写一个类似 AppHost 的应用通过编写这个应用可以了解在 dotnet 启动之前需要做哪些步骤在开始之前我推荐大家拉下我的代码到本地通过自己更改实际修改代码可以理解整个 dotnet 的启动的 Native 部分逻辑本文放在 github 欢迎小伙伴访问在代码仓库里面保护了两个模块一个就是 SampleHost.vcxproj 包含的代码这里就是 Native 的逻辑。另一个就是 ManagedLibrary 也就是咱 C# 的托管代码。下面让我来告诉大家这个仓库可以如何玩先进入 ManagedLibrary 文件夹双击执行 build.bat 文件此时将会执行 dotnet 的发布命令可以在发布之后进入HostWithMscoree\ManagedLibrary\bin\Debug\net5.0\win-x86\publish\ 文件夹看到发布之后的内容现在咱准备自己写一个 AppHost 应用这个应用将支持从其他的路径找到运行时然后执行 ManagedLibrary.dll 的逻辑。换句话说就是咱接下来的做法就是在 C 盘创建两个文件夹分别是 c:\lindexi\Code\HostWithMscoree\dll\ 和c:\lindexi\Code\HostWithMscoree\framework\ 文件夹将 ManagedLibrary.dll 文件复制到 c:\lindexi\Code\HostWithMscoree\dll\ 文件夹将 HostWithMscoree\ManagedLibrary\bin\Debug\net5.0\win-x86\publish\ 文件夹里面除了 ManagedLibrary 相关的文件外的其他文件复制到 c:\lindexi\Code\HostWithMscoree\framework\ 文件夹也就是说 ManagedLibrary.dll 的运行时框架都在 framework 文件夹而 ManagedLibrary.dll 自己在 dll 文件夹里面。此时就需要在 dotnet 启动逻辑里面包含了去 c:\lindexi\Code\HostWithMscoree\framework\ 文件夹寻找运行时的过程才能让 ManagedLibrary.dll 跑起来请打开 HostWithMscoree\SampleHost.sln 文件此时我期望你的 VS 上安装完成了 C 的负载如果有提示缺少的部分还请自行安装。打开之后请切换到 x86 配置下因为咱刚才发布的 dotnet 应用是 x86 应用打开 HostWithMscoree\host.cpp 文件这里面将是整个核心的逻辑。这部分的逻辑相对清晰但是知识点非常多详细请看官方的 Native hosting 文档在 HostWithMscoree\host.cpp 文件的 wmain 方法就是这个 SampleHost 的入口方法。可以看到这里被我定制了两个常量路径int wmain(int argc, wchar_t* argv[]) {printf(Sample CoreCLR Host\n\n);// 替换下面的代码wchar_t* application Lc:\\lindexi\\Code\\HostWithMscoree\\dll\\ManagedLibrary.dll;const wchar_t* coreCLRDirectory Lc:\\lindexi\\Code\\HostWithMscoree\\framework\\;// 忽略代码 } 我在上面代码分开了 application 应用所在的文件夹路径以及应用的运行时所在的文件夹路径作为两个不同的常量路径当然了第一个实际上代码上不是常量只是逻辑上是常量用于在后续使用。请大家根据自己的需要更改路径在 c:\lindexi\Code\HostWithMscoree\framework\ 文件夹里面存放的就是 ManagedLibrary 项目里面除了 ManagedLibrary.dll 和 exe 等文件外的其他文件也就是说 framework 文件夹里面存放的是当前 ManagedLibrary.dll 的运行时和框架所有文件而 application 对应的文件夹里面就只有 ManagedLibrary.dll 一个文件因为其他的文件咱也不需要用到。如 ManagedLibrary.exe 其实就是 AppHost 文件这个文件的功能就是作为 dotnet 的启动入口而这个功能就是咱的 SampleHost 所要完成的功能。也就是说咱将使用 SampleHost 代替 AppHost 也就是 ManagedLibrary.exe 文件来作为 dotnet 的启动入口配置完成之后请按下 F5 运行起来。如果看到只是一闪而过还请在适当地方添加断点哈因为 C 程序在 VS 上没有做和 C# 一样的优化在执行完成之后不退出控制台如果能运行成功可以看到如下界面只有一句 这是在 dotnet 的输出 是跑在咱的 dotnet 应用里面的其他都是 SampleHost 的这样咱就完成了一个 dotnet 启动器可以从指定的路径找到运行时和框架然后运行指定路径的应用在跑起来之后可以先看看这个项目里面的代码和注释咱按照代码的顺序一步步告诉大家这是在做什么官方的例子被我进行了一些魔改原因是本文的这个代码是微软官方的例子但是微软在 dotnet 5 时删除了这个例子因此需要在 https://github.com/dotnet/samples 项目里面切换 commit 到 a8804d38692d6c2a4bf9e78d0058edaf8c9cf955 才能找到本文的例子本文的例子放在 core/hosting/HostWithMscoree 文件夹官方的例子本身是给 dotnet core 2.2 以及更低版本使用的。但是在 dotnet 5 的时候依然能用这部分机制依然写在了官方的文档里面。但本文的逻辑依然只是一个 demo 级如果做到产品上还请大家先理解代码细节根据自己的需求更改同时也需要处理好各个非预期的情况在代码的开始就是我魔改的部分这部分适用于大家的快速开始int wmain(int argc, wchar_t* argv[]) {printf(Sample CoreCLR Host\n\n);// 替换下面的代码wchar_t* application Lc:\\lindexi\\Code\\HostWithMscoree\\dll\\ManagedLibrary.dll;const wchar_t* coreCLRDirectory Lc:\\lindexi\\Code\\HostWithMscoree\\framework\\;// 忽略代码 } 尽管这里的 main 函数看起来有点诡异但这就是入口点没错了。接下来就是通过咱上面的 coreCLRDirectory 的值去加载 CoreClr.dll 文件加载逻辑大概如下 const wchar_t* coreCLRDirectory Lc:\\lindexi\\Code\\HostWithMscoree\\framework\\;// 下面代码相当于 string coreRoot coreCLRDirectory; 而已wchar_t coreRoot[MAX_PATH];wcscpy_s(coreRoot, MAX_PATH, coreCLRDirectory);HMODULE coreCLRModule;coreCLRModule LoadCoreCLR(coreRoot);HMODULE LoadCoreCLR(const wchar_t* directoryPath) {wchar_t coreDllPath[MAX_PATH];// 下面代码其实就是 coreDllPath c:\\lindexi\\Code\\HostWithMscoree\\framework\\ \\ coreclr.dll;wcscpy_s(coreDllPath, MAX_PATH, directoryPath);wcscat_s(coreDllPath, MAX_PATH, L\\);wcscat_s(coreDllPath, MAX_PATH, coreCLRDll);// 以下是核心代码通过 LoadLibraryExW 加载 CoreClr.dll 文件// Snippet2HMODULE ret LoadLibraryExW(coreDllPath, NULL, 0);// /Snippet2if (!ret){// This logging is likely too verbose for many scenarios, but is useful// when getting started with the hosting APIs.DWORD errorCode GetLastError();wprintf(LCoreCLR not loaded from %s. LoadLibrary error code: %d\n, coreDllPath, errorCode);}return ret; }// 这是在 Windows 下的写法在 Windows 下是加载 CoreClr.dll 文件 // Main clr library to load // Note that on Linux and Mac platforms, this library will // be called libcoreclr.so or libcoreclr.dylib, respectively static const wchar_t* coreCLRDll Lcoreclr.dll; 也就是说通过 LoadLibraryExW 这个 win32 方法加载了 CoreClr.dll 文件。返回 HMODULE 给了 coreCLRModule 变量。这就是为什么 dotnet core 能独立框架的一个原因也是为什么 dotnet core 可以不依赖系统安装的运行时框架的原因了。原因就是在 dotnet core 里面运行让 Host 程序去寻找启动所需要的执行引擎(这个词实际是不存在的说的只是 CoreClr.dll 而已) 也就是说允许让开发者自己定义整个运行时和框架所在的路径因此只需要在我的例子程序里面更改 coreCLRDirectory 变量的路径即可实现自定义设置共享框架的路径。本质的共享框架和独立发布的框架没有差别只是独立发布的框架只是给一个应用使用而共享的框架可以给多个应用使用。可以在一个团队内发布的多个软件都使用相同的框架文件夹这样这个框架文件夹就完全由团队控制同时团队里面多个软件之间也不需要额外去安装框架减少重复文件接下来就是通过 CoreClr.dll 提供的 GetCLRRuntimeHost 方法获取 Clr 运行时 Host 对象 // 从 CoreClr.dll 里面获取 GetCLRRuntimeHost 方法// 相当于拿到 HRESULT GetCLRRuntimeHost(Guid id, out ICLRRuntimeHost4 runtimeHost); 方法FnGetCLRRuntimeHost pfnGetCLRRuntimeHost (FnGetCLRRuntimeHost)::GetProcAddress(coreCLRModule, GetCLRRuntimeHost);// 通过 pfnGetCLRRuntimeHost 拿到 runtimeHost 对象// 以下写法的意思是 HResult hr pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost4, out var runtimeHost);Guid IID_ICLRRuntimeHost4 new Guid(xxx-xxx-xx-xx-xxx); // 当然了实际写法是 EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF); 只是这样写很诡异ICLRRuntimeHost4* runtimeHost;HRESULT hr pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost4, (IUnknown**)runtimeHost); 在拿到 runtimeHost 对象之后就可以调用 Start 方法启动运行时了如下面代码 hr runtimeHost-SetStartupFlags(/*一些不需要关注的启动配置*/);if (FAILED(hr)){printf(ERROR - Failed to set startup flags.\nError code:%x\n, hr);return -1;}// 启动运行时将会初始化 JIT 和 GC 和加载器等模块。运行到这里可以认为 dotnet 已经热完成了// Starting the runtime will initialize the JIT, GC, loader, etc.hr runtimeHost-Start(); 在完成了运行时的启动之后就可以来创建 AppDomain 来运行咱的业务端的 dotnet 托管代码了在 dotnet 里面有一个概念是程序集加载程序集需要加载到一个 AppDomain 上如果大家玩过插件开发这部分将会更好的理解。想要让咱的业务端的 dotnet 托管代码运行就需要加载咱的程序集需要将程序集放入一个 AppDomain 上 // 进行创建 AppDomain 的配置int appDomainFlags APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS | APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP | ... ;// 以下逻辑用 C 写需要太多代码了因此我就换 C# 系的代码来写// 哪些 dll 或 exe 将会被加入寻找程序集加载路径// 所有放在 coreRoot 路径下的 exe 和 dll 和 winmd 都会加入Liststring trustedPlatformAssemblies DirectoryHelper.GetFiles(coreRoot, *.exe|*.dll|*.winmd);var application c:\\lindexi\\Code\\HostWithMscoree\\dll\\ManagedLibrary.dll;string targetAppPath Path.GetDirectoryName(application);// APP_PATHS// App paths are directories to probe in for assemblies which are not one of the well-known Framework assemblies// included in the TPA list.//// For this simple sample, we just include the directory the target application is in.// More complex hosts may want to also check the current working directory or other// locations known to contain application assets.string appPath targetAppPath;Liststring appPaths new Liststring() { appPath };// APP_NI_PATHS// App (NI) paths are the paths that will be probed for native images not found on the TPA list.// It will typically be similar to the app paths.// For this sample, we probe next to the app and in a hypothetical directory of the same name with NI suffixed to the end.Liststring appNiPaths new Liststring() { targetAppPath ; targetAppPath NI };// NATIVE_DLL_SEARCH_DIRECTORIES// Native dll search directories are paths that the runtime will probe for native DLLs called via PInvokeListstring nativeDllSearchDirectories new Liststring(){ appPath ; coreRoot };Liststring platformResourceRoots appPaths;// 这是传入的参数参数是 Key 和 Value 对的也就是下面的 propertyKeys 和 propertyValues 的值是一一对应的// Setup key/value pairs for AppDomain propertiesstring[] propertyKeys new[]{TRUSTED_PLATFORM_ASSEMBLIES,APP_PATHS,APP_NI_PATHS,NATIVE_DLL_SEARCH_DIRECTORIES,PLATFORM_RESOURCE_ROOTS};// Property values which were constructed in step 5ListListstring propertyValues new ListListstring(){trustedPlatformAssemblies,appPaths,appNiPaths,nativeDllSearchDirectories,platformResourceRoots};// 以上就是配置拿到了 propertyKeys 和 propertyValues 组成了属性传入// 下面继续回到 C 代码hr runtimeHost-CreateAppDomainWithManager(LSample Host AppDomain, // Friendly AD nameappDomainFlags,NULL, // Optional AppDomain manager assembly nameNULL, // Optional AppDomain manager type (including namespace)sizeof(propertyKeys) / sizeof(wchar_t*),propertyKeys,propertyValues,domainId); 上面代码为了表述方便我将部分 C 的代码翻译为 C# 来写这样瞬间代码就清洁了非常多此时拿到的 domainId 就能代表这个 AppDomain 了。下一步是加载咱的业务端的程序集开始执行 hr runtimeHost-ExecuteAssembly(domainId, targetApp, argc - 1, (LPCWSTR*)(/*参数*/ NULL), exitCode); 上面代码执行之后将会调用进咱 C# 托管代码的 Main 函数里面。进入这个函数之后的逻辑就和这个启动 Host 应用没有什么关系了当然了进入这个函数做的事情可是特别复杂的包括 JIT 将 IL 进行翻译为机器指令申请内存执行托管逻辑等这就需要农夫大大的 《.NET Core底层入门》 这本书以及伟民哥翻译的 《.NET内存管理宝典 - 提高代码质量、性能和可扩展性》 这本书在 C 里面最后一步是等待 dotnet 应用完成之后清理一下内存 runtimeHost-UnloadAppDomain(domainId, true /* Wait until unload complete */);runtimeHost-Stop();runtimeHost-Release(); 其实如果只是作为 Host 是可以不清理的进程关了自动就清理了其实可以看到核心的代码是特别少的只有下面这几句// 加载 CoreClr.dll 文件 coreCLRModule LoadCoreCLR(coreRoot);// 拿到 GetCLRRuntimeHost 方法 FnGetCLRRuntimeHost pfnGetCLRRuntimeHost (FnGetCLRRuntimeHost)::GetProcAddress(coreCLRModule, GetCLRRuntimeHost);// 使用 GetCLRRuntimeHost 方法拿到 runtimeHost 对象 HRESULT hr pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost4, (IUnknown**)runtimeHost);// 创建 AppDomain 对象 runtimeHost-CreateAppDomainWithManager(/*忽略代码*/ domainId);// 运行程序集 runtimeHost-ExecuteAssembly(domainId, targetApp);// 清理 runtimeHost-UnloadAppDomain(domainId, true /* Wait until unload complete */); runtimeHost-Stop(); runtimeHost-Release(); 使用上面代码就能实现自己做一个 dotnet 的 Host 加载自己定义的运行时框架文件夹以及自己创建第一个 AppDomain 加载程序集另外上面代码的另一个功能是让 Native 的其他语言编写的应用可以加载使用 dotnet 编写的库。上面代码除了使用 ExecuteAssembly 运行程序集之外还可以调用程序集里面的某个静态方法。只需要调用 runtimeHost-CreateDelegate方法就可以但这个逻辑在 dotnet 5 下有更改在 dotnet 5 下提供了更方便的方式但不在本文范围内本文告诉了大家如何自己实现 dotnet 的启动之前的逻辑其实就是各个方法的调用本文也只是告诉大家如何调用而已关于这些方法的执行逻辑以及更多可以使用的参数还请大家去开源仓库里面找代码
http://www.pierceye.com/news/737102/

相关文章:

  • 网站seo规范南昌it制作电商网站的公司
  • 深圳网站设计 工作室深圳品牌设计工作室
  • 手机网站静态动态wordpress注意
  • 什么网站没人做v5shop微分销系统
  • 做鞋子的网站品牌vi设计包括哪些
  • 做产品类的工作上什么网站好asp.net做的网站模板下载
  • 金融公司网站规划方案我司网站改版上线网站建设
  • 城乡与住房建设部网站首页深圳响应式设计企业网站
  • 做网站 带宽 多少钱做电影网站的服务器需要多大
  • 西安网站建设全包用手机制作游戏的软件
  • 哪个网站生鲜配送做的好drupal wordpress网站
  • 网站后台需要多少建设部举报网站
  • 重庆建筑证书查询网站wordpress博客怎么访问不了
  • 网站案例鉴赏wordpress html5视频
  • 免费申请网站 主机 空间网站不稳定
  • 建立个人网站视频教程中国空间站和国际空间站对比
  • 佛山网站seo推广推荐一个专门做海鲜的网站
  • 长春网站建设与健网站外链如何做
  • 网站开发国内现状网站建设与维护教学计划
  • 如何解决网站图片打开慢网站如何做跳转
  • 网站开发作用大学生网络营销策划书
  • 有域名了如何建网站用自己的身份做网站备案
  • 免费的黄冈网站有哪些平台游戏软件上海网站建设自学
  • 网站建设摊销几年wordpress怎样建立二级菜单
  • 营销方案案例北京搜索引擎优化seo专员
  • 网站建设是什么科目wordpress 火车头
  • 做网站需要什么专业方向的员工wordpress yeti
  • 网站建设项目登记表长沙建网站培训机构
  • 拖拽建站平台福州小学网站建设
  • 网站定制套餐建设企业网站需要注意的问题