利用DelayLoad来优化应用程序的性能.拦截API.

本地大模型部署选型指南:Ollama、vLLM与llama.cpp实战对比 大模型本地化部署已成为工业控制、医疗影像、金融合规等强监管与低延迟场景的刚需技术。其本质是将模型从云端服务还原为可控、确定、主权在握的终端工具,核心诉求围绕数据不出域、响应可预测、成本可持续三大刚性约束展开。在此背景下,Ollama以开箱即用降低入门门槛,vLLM凭借PagedAttention实现高并发工业级吞吐,llama.cpp则通过零依赖C++推理支撑嵌入式与边缘全平台落地。三者并非简单性能递进,而是面向不同硬件资源(如GPU显存容量)、业务指标(如P99延迟≤80ms)和团队能力(如是否具备CUD 阅读详情
创建时间:2001-06-22
文章属性:转载
文章来源: http://snake12.top263.net
文章提交: stardust (bugmail_at_telekbird.com.cn)

中文翻译 by snake

    在 1998年12月的MSJ出版刊物中, Jeffrey和我写了关于 在 vc6中使用DelayLoad 功能的专栏.最终结果,是证明了它是多么cool.但是,不幸的是,还有很多人不了解DelayLoad,他们以为这个新特点是 最新版本的WINNT才有的.
    在开始的时候,让我重申一遍:DelayLoad不是最新的操作系统带的特有功能,它可以在任何win32系统中起作用.我将写一个简单例子来说明. DelayLoadProfile, 实现了一个很小功能,很多程序都可以得益于它.


预览:
    通常的,当调用一个dll中的函数时,连接器会将dll和函数加入你的可执行文件.最后,所有引用的函数会放在imports段中.  当加载该程序的时候,win32程序加载器会扫描所有imports段的每个dll.加载,和重新定位imports段的所有函数,将信息写入 引入地址表(ImportAddress Table, IAT).简单说来,IAT就是一个函数指针的表.调用该 引入函数的时候,就到IAT中去找.  那么,DelayLoad的机理是什么呢?当你为一个Dll进行"DelayLoad"的时候,连接器不将原来的值放入imports段,相反,它为每个DelayLoad的引入函数的名称和地址,生成一个小的根区, 备份下来。第一次引用的时候,它调用LoadLibrary加载Dll,然后,它调用GetProcAddress取得该函数的地址。最后,改写自己在IAT的值,以便以后的程序可以直接调用.
    上面的是简化的步骤.实际上,根区是一小段代码,它以静态的方式连接到可执行文件中.代码在delayimp.lib中,必须被 连接程序引用.并且,该代码要足够智能,当一个函数第一次被引用的时候,要调用LoadLibrary,以后调用就不用引用了.  和引用Dll相比,DelayLoad不会加太多的时间和空间,这种方式 调用LoadLibrary只会引起稍微一点点的性能损失.每次程序启动,在针对引入表的函数地址定位的时候,依次对DelayLoad引入的调用GetProcAddress,相对于Win32加载器来说,所损失的性能也可以忽略不记.
    然而,DelayLoad带来的好处也是不可比拟的.例如:如果你的程序从来没有 从Delay调用引入的函数,Dll的第一次是不会被加载的。有时候,这个情况的出现频率出乎你想象。假如,你的程序中,包含打印的代码,毫无疑问,即使用户没有使用打印功能,你的程序也一定要加载winspool.drv。在这种情况下,使用DelayLoad,你就不必加载和初始化Winspool.drv.
    另外一个好处就是:DelayLoad可以避免调用某些目标平台不存在的API。例如,假如你的程序需要调用AnimateWindow,这个API在Win2000和Win98中存在,但是在Win95和WinNT4中,就不存在,假如你用常规的方式调用AnimateWindow,那么,你的程序将不能再早期的平台中运行。然而,你可以用DelayLoad进行对AnimateWindow的加载检查。这样,你就不必改写你的代码为LoadLibrary和GetProcAddress的方式了。
    DelayLoad是很容易使用的。当你决定哪个dll你想使用DelayLoad,只需要简单的增加/DELAYLOAD:DLLNAME。其中,DLLNAME是相关的DLL文件名。你还需要增加DELAYIMP.LIB到连接库中,你也需要原来的LIB,例如,SHELL32.LIB。把全部放到一块,连接的命令就如下: SHELL32.LIB /DELAYLOAD:SHELL32.DLL DELAYIMP.LIB  很不幸,Visual Studio 6.0 IDE 不提供一个简单的方法去实现一个Dll的DelayLoad。所以,你必须手工加入:/DELAYLOAD:XXX 命令行到 "Project settings"->"Link"->"Project Options"中。
  
什么时候需要DelayLoad:
    当你有小的工程,它调用了多个dll,就是一个好的DelayLoad候选例子。然而,工程可能在以后由于其它开发者的加入而变大,很容易丢失调用dll的跟踪。我通常用sdk中的depends.exe。一个只有少数函数要引入的dll就是一个好的开始。
    然而,我想找到一个简单的,自动的方法来跟踪。于是,出来了DelayLoadProfile程序。它是一个exe,可以监视你的exe文件对dll的调用,直到你的exe结束。它打印出dll被调用的情况的汇总,包括多少个dll被调用,每个dll有多少个函数被引入。
    我在这里强调:DelayLoadProfile只是针对exe有效,当它涵盖你的程序所关联的所有dll的时候,有时会造成一点点复杂。DelayLoadProfile只给你哪个dll可以用DelayLoad开关的暗示,你最好在不确定的时候,使用原来的处理方法。

DelayLoadProfile:详细描述
    其实DelayLoadProfile的原理很简单:重定向 exe中,IAT的函数的指针到一段根区。根区简单的标志一下,引入的函数被调用了。然后,跳入原来的Win32加载提供的IAT地址。只是,难的是如何实现。
    第一,你必须决定,要在哪里运行你的代码,实现对exe的IAT入口的更改,把他们指定到那段根区去。这些都是在进程外完成。这样可以避免你的代码牵涉到目的exe进程中。这个可以用遍历所有的数据结构,定位和修改IAT结构的方法。我在这里利用了很多ReadProcessMemory调用。
    接着的艰苦工作是要在和目的exe相同的进程空间里完成。几乎是很琐碎的工作:遍历所有的数据结构,建立根区,从定向IAT入口,然后在完成的时候,汇总结果。然而,为了完成进程空间的工作,在exe进程运行的时候,一些 DelayLoadProfile代码必须被加载到目的exe的进程空间。这个是我要做的。
    当确认到需要在目的进程中,加载我的代码的时候,下个问题就是如何把我的代码加入到目的进程中。其中一个选择就是,要求用户连接我的DelayLoadProfile库,这个会造成用户的很大量的对他们源代码工程,或者Makefile的更改,所以,我不能采用,现在需要一个完全自动化的方法。
    在这点上,我想到了加载程序,然后,插入我的DelayLoadProfiledll进去,一个技术就是用CreateRemoteThread,在目标进程,创建一个LoadLibrary的线程。我放弃了这个,因为,win9x中,不提供CreateRemoteThread.
    很久以前的MSJ读者可能记得我5年前写的一个叫APISPY32的程序。它加载一个进程,插入一个dll来记录API的调用。那个有点像我今天的DelayLoadProfile工作。然而,我在Win200中,调用那个dll失败。有一点点问题。我觉得现在是时候要重读那段代码,并且改正那个错误了。
  
继续深入:
    重新温习一下,DelayLoadProfile包含2部分,一,是进程加载功能,它会注射一个dll到你的进程的地址空间。然后,那个dll扫描你的所有的exe IAT,重新定向他们到dll创建的根区中。当你的程序完成后,注射的dll会扫描所有的根区,统计出多少dll和函数它调用的。如果你曾经用过APIMON的相关部件,你将认出类似的技术细节。
    完成所有的工作,包括 监视 一个程序的引入的dll,叫DelayLoadProfileDLL.(看Figure 1).它用到DLL_PROCESS_ATTACH和DLL_PROCESS_DETACH来初始化2个主要的工作。
    当DllMain获得DLL_PROCESS_ATTACH的消息的时候,DelayLoadProfileDLL调用PrepareToProfile(),在PrepareToProfile中,代码加载目的EXE的IAT,对于每个它发现的引用的DLL,代码还检测是否安全的重定向IAT。通过IsModuleOKToHook函数来检测,大多数情况下,是安全的,因此,PrepareToProfile包括了RedirectIAT函数。
    RedirectIAT是比较复杂的函数。如果你理解了 winini.h中的引入相关数据结构,你将得到很大的帮助。首先,函数定位IAT和相关的引入名字表,然后,计算有多少个IAT入口,扫描所有的IAT,查找NULL的指针。得到了数目后,程序将创建一个DLPD_IAT_STUB根区,每个根区对应一个IAT入口。
    最后,代码重新扫描IAT,获取每个IAT入口的地址,用根区的一个包含JMP指令的地址,替换IAT入口。它还扫描下一个IATDLPD_IAT_STUB根区。我在后面将还会继续解析。
    在重定向IAT入口的根区中,有2个值得提起:1,IAT常常被放到EXE的只读段,通常,尝试改写只读段,会引起访问违规,幸运的,VirtualProtect允许你更改一个目的地址的属性。现在必须更改iat的属性为读/写。完成后,代码要恢复IAT段原来的属性。
    另外一个要注意的地方,就是在重定向IAT的时候,有数据引入的问题。虽然程序员们很少这样做,但是,很容易用增加的代码去导入数据。vc++运行库DLL(MSVCRT.DLL)有数据导出。如果重定向一个数据IAT的入口,会导致问题。
    那么,如何判断一个IAT是数据呢?一个商业的软件,应该用准确的算法来判断一个IAT入口的类型。但是,我在这里用了一个快捷方法。就是IsBadWritePtr。如果IAT包含的指针是可写的,那么,很可能是一个数据指针。如果是只读的,那么,应该是一段代码。这个测试合适吗?不,但是,它对DelayLoadProfile是足够了。
    现在看一下根区,在DelayLoadProfileDLL.h中定义的DLPD_IAT_STUB结构包含着代码和数据。简单来说,就是如下:
  CALL DelayLoadProfileDLL_UpdateCount
  JMP xxxxxxxx //original IAT 地址
  DWORD count
  DWORD pssNameOrOrdinal

    当exe调用其中一个重定向的函数时,控制权被转到根区的CALL指令中,调用DelayLoadProfileDLL.CPP中的DelayLoadProfileDLL_UpdateCount函数,在call指令返回时,继续调用jmp 跳转到IAT原来取得的地址中。Figure2显示了结构示意图。
    汇编高手会对DelayLoadProfileDLL_UpdateCount函数能确定根区的COUNT字段的地址,感到疑惑,通过快速的察看代码,会发现DelayLoadProfileDLL_UpdateCount会在堆栈中,查找到返回地址。返回地址指着JMP xxxxxxxx指令。因为,CALL调用总是5个字节,根据这些算法,可以确定COUNT字段的地址。
    有一个问题值得提醒,就是DelayLoadProfileDLL_UpdateCount没有调用PUSHAD和POPAD指令来保存/回复CPU寄存器的值。这段代码在很多程序上都工作正常,但是,却在一些函数中,不能正常工作。最后,发现 MSVCRT.DLL的__CxxFrameHandler和 _EH_prolog有问题,这2个函数 期望eax寄存器被设置成某个值。然而,DelayLoadProfileDLL_UpdateCount更改了EAX.  既然这个是由于EAX引起的问题,那么,我增加了PUSHAD和POPAD,昏倒,问题还存在。在遭受挫折后,我检查了汇编生成的代码。通常,VC6编译器会插入将所有本地变量都初始化为0xCC的代码。这些代码会在PUSHAD和POPAD前,将EAX改变。我只好移去/GZ的选项。


结果报告:
    当你的进程停止的时候,系统对所有加载的DLL发送一个DLL_PROCESS_DETACH消息。DelayLoadProfileDLL使用这个选项来搜集程序运行过程中,获得的结果。也是说,再次遍历所有的根区单元。收集所有获得的数据,输出。
    在DelayLoadProfileDLL安装的阶段,重定向IAT,它保存exe的IAT到一个公共的变量出g_pFirstImportDesc。在关闭的过程中,ReportProfileResults用到这个指针来再次遍历引入段。如果这个IAT是被重定向的,那么,第一个IAT的指针应该指到第一个为该DLL分配的DLPD_IAT_STUB根区内存。当然,代码保持了基本的测试方法,如果某些地方不正确,DelayLoadProfileDLL忽略该特定的dll。
    总的说来,所有的都很正常,并且,第一个IAT入口指到我的根区单元。对于每个DLL,代码反复的遍历所有的根区。每个相关的根区,它的包含的字段的值,将加到该DLL的总计数。当遍历完成,ReportProfileResults格式化一个字符串,输出该dll的名字,和调用的总次数。代码还用OutputDebugString广播该结果。

加载和注射:
    本程序加载你的exe,注射DelayLoadProfileDLL.dll将会调用,(你猜到了),是DelayLoadProfile.exe(源文件可以在msj的网站找到, http://www.microsoft.com/msj)。这个代码主要继承了CDebugInjector类。我将简单的介绍它。函数主要包含了目的exe的命令行,并且传递到CDebugInjector::LoadProcess。如果进程被成功创建,函数会告诉CDebugInjector,哪个dll会被注射,既然是这样,和DelayLoadProfile.exe同目录的DelayLoadProfileDLL.DLL,将会被加载。
    在运行目标程序之前,最后的步骤是调用CDebugInjector::SetOutputDebugStringCallBack。当DelayLoadProfileDLL用OutputDebugString来输出报告结果的时候,CDebugInjector看到他们,然后传递他们到你已经注册的回调函数中。这个回调函数只是用printfs输出字符串到控制台。最后,函数调用CDebugInjector::Run。这样,目的进程开始运行,当时机成熟,注射dll进去。  描述3(hoodtextfigs.htm#fig3)说明了CDebugInjector类。这是代码实现的地方。CDebugtInjector::LoadProcess创建了目的进程,作为一个调试进程,它的分支已经在msdn的很多文档中讨论过了,这里,不想作太多具体的讨论。
    调试进程运行后(这里是DelayLoadProfile)进入了一个循环,不断的调用WaitForDebugEvent和ContinueDebugEvent,直到调试停止。每次WaitForDebugEvent返回,都有些东西发生在调试程序身上。可能是一个异常(包括断点),或者加载一个dll,或者创建一个线程,或者其他事件。WaitForDebugEvent文档历包含了所有的可能的事件。CDebugInjector::Run过程包含这个循环的代码。
    那么,如何让目的进程作为一个被调试进程,帮助你注射一个dll呢?一个调试进程可以控制的被调试进程的执行过程。每次被调试程序有一个信号事件发生,它都会暂停,等待调试者调用ContinueDebugEvent继续运行。了解了这个,一个调试进程可以增加代码到被调试进程的空间,和临时改变被调试者的寄存器值,以便增加的代码运行。
    在某些特定场合,CDebugInjector合成了一小段代码根区来调用LoadLibrary。LoadLibrary的dll名字参数,指到要被注射的dll的名字。CDebugInjector写那个根区(和相关联的dll名字)到被调试者的地址空间。然后,调用SetThreadContext来改变被调试者的指令寄存器,运行LoadLibrary根区。所有的相关代码在CDebugInjector::PlaceInjectionStub过程中。
    立刻的,根区中的LoadLibrary调用后,是一个断点(int 3)。这个暂停被调试者的运行,交回控制权给调试的进程。调试者用SetThreadContext,恢复指令寄存器和其他寄存器到原来的值。另一次调用ContinueDebugEvent,被调试者在dll注射的状态下,继续运行。没有人知道发生了什么事情。
    如果你不想那么多,这个注射进程不会觉得太难,但是,一些有兴趣的东西,弄复杂了事情。例如,什么时候创建根区,改变运行代码,才是适当呢?你不能在CreateProcess后立刻做这个,因为,引入的dll还没有被映射到内存中,WIN32加载器还没有建立exe的IAT。相当于:太早了。
    最后,我决定让被调试者运行,直到碰到了第一个断点。我在程序入口处,设置了一个自己的断点。当第2次中断被触发,CDebugInjector知道目的进程的DLL,都被初始化了(包括Kernel32.dll)。但是,在exe中,还没有代码运行。现在是时候注射DelayLoadProfileDLL.DLL了。
    顺便说一下:断点从哪里来呢?通过定义,一个被调试的win32的进程,在运行之前,会调用DebugBreak(也是int3),在我早期的apispy32代码中,我选用了最初的DebugBreak来做注射。在win2k中,非常不幸,这个DebugBreak在Kernel32.dll初始化之前,被调用,那么,CDebugInjector设置它的断点到exe即将获得控制的地方,那么,kernel32.dll被初始化了。
    在之前,我提到在LoadLibrary调用后,发生的一个断点。这是第3个CDebugInjector要处理的断点,所有的处理不同断点的技巧,可以参考CDebugInjector::HandleException。
    另外一个关于注射dll的有兴趣的问题,就是在那里写LoadLibrary单元,在winnt4.0以后,你可以用VirtualAllocEx来为某个线程申请内存。我采用了这个方法。现在,剩下不能支持VirtualAllocEx的Win9x,针对这个问题,我利用了win9x内存映射文件的一个特殊的特性,这些文件在所有的地址空间都可见。并且,是同一个地址。我简单的利用系统页面文件作为支持,创建了一个小的内存映射文件,写了LoadLibrary根区进去。该根区对于被调试程序,是可见的。更多的详细情况,请看文章首部的连结的CDebugInjector::GetMemoryForLoadLibraryStub。

使用DelayLoadProfile:
    DelayLoadProfile是一个输出结果到标准输出的命令行程序。在命令行提示中,运行DelayLoadProfile,制定目的程序,和它需要的参数,例如:  DelayLoadProfile notepad c:/autoexec.bat下面是针对(windows 2000 Release Candidate2)的calc.exe, 运行DelayLoadProfile的结果:
   [d:/column/col66/debug]delayloadprofile calc
   DelayLoadProfile: SHELL32.dll was called 0 times
   DelayLoadProfile: MSVCRT.dll was called 9 times
   DelayLoadProfile: ADVAPI32.dll was called 0 times
   DelayLoadProfile: GDI32.dll was called 60 times
   DelayLoadProfile: USER32.dll was called 691 times
    我简单的开始calc,然后,立即关闭。注意到,shell32.dll和advapi32.dll都没有调用,这2个dll是最初的calc用来DelayLoad的候选。
    你将回觉得奇怪,为什么calc调用shell32.dll,你没有调用它。如果你针对CALC,调用DumpBin /IMPORTS或者Depends.exe分析,你将看到,CALC从SHELL32.DLL中引入的函数只有ShellAboutW。简单来说,只有你选者CALC的HELP|About Calculator菜单项,才会完全的调用SHELL32.DLL入内存。这个是一个最明显的/DELAYLOAD显示其价值的例子。顺便说,SHELL322.DLL简单的,毫无条件的加载SHLWAPI.DLL和COMCTL32.DLL,并且初始化。
    如果只是因为DelayLoadProfile报告一个dll没有被调用,或者很少调用,你就可以自动的 延迟加载,你要认真的确定,哪一个暗中连结的dll,你要使用/DELAYLOAD。这种情况下,如果由于其他的依赖,你的DLL要被自动的加载和初始化,那么,/DELAYLOAD就没有意义了。平台sdk带的Depends.exe是一个很有用的工具,可以看到一个dll的使用情况。
    在你的测试过程中,你的测试的程序的个数,也是值得考虑的。如果你测试了所有的程序的功能,所有的被引入的dll都包括了。个人认为,我觉得应该尽量缩小初始化时间,这个可能是意味着你只是开始你的程序,然后关闭它。要加快初始化,就依次加载dll。用户都是主观的由启动时间判断你的程序的速度。
    我发现几个DLL可以从/DELAYLOAD处得益。从上所述,SHELL32.DLL是其中一个。另外一个是打印支持的WINSPOOL.DRV。既然很多用户都不经常打印,那么,就是很好的采用者。还有,类似的OLE32.DLL和OL3AUT32.DLL。一个多态的程序,在小容器中,用到COM和OLE,那么,相关的DLL也是可以选用的。例如,WIN2000的CDPLAYER.EXE和OLE32.DLL连接,用到了CreateStreamOnHGlobal函数。但是,在通常的情况下,我没有觉察到这个函数被调用。
    DelayLoadProfile并不是没有它的毛病,当我在很多程序针对IAT,用DelayLoadProfileDLL成功测试后,你可能还会碰到不正确的运行的情况。要完全解决这个问题,就超出了本次讨论的范围。然而,如果你成功解决了其中一个问题,请让我知道。我将在将来的一天更新DelayLoadProfile。  我知道某些引入mfc42.dll和mfc42u.dll的程序会和DelayLoadProfile冲突,于是,我采用了一个方法,在DelayLoadProfileDLL.cpp,有一个IsModuleOKToHook函数,我放了MFC42.DLL,MFC42U.DLL和KERNEL32.DLL进去。(你不能用 /DELAYLOAD 和KERNEL32.DLL关联,因为,是没有作用的)如果一个特别的DLL会出问题,你应该放到IsModuleOKToHook函数中。  我希望DelayLaodProfile会帮助你的程序采用/DELAYLOAD。我以后应该还会有时间去更新一些专业的带骂,并且,我还希望听到你的成功的故事。

    如果你对<under the hook>有任何建议,请mail给matt:matt@wheaty.net,或者 http://www.wheaty.net

摘自 <Microsoft System Journal>2000年2月刊
PHP Swoole AOT编译:打造零依赖Windows原生EXE PHP传统上是解释型脚本语言,依赖php.exe和复杂运行环境,导致Windows端交付困难。Swoole 5.0+引入的AOT(Ahead-of-Time)编译技术,通过LLVM IR生成、静态链接与内核模块化,将PHP代码、运行时及扩展(如协程、HTTP服务器)直接编译为独立Windows PE可执行文件。该方案不依赖VC++ Redist、无需安装PHP环境,彻底解决部署不确定性问题,显著提升交付可信度与运维确定性。适用于内部工具、信创轻服务、工控采集客户端等需双击即用、注册为Windows服务的生产 阅读详情

相关推荐

Windows平台DLL延时加载技术实现指南

IAT(Import Address Table,导入地址表)是PE(Portable Executable)文件格式中的一个数据结构,它位于可执行文件或DLL文件的节区中,用于存储导入函数的实际内存地址。当一个可执行文件被加载到内存时,操作系统会解析每个导入的DLL函数,并将它们的地址写入IAT。IAT的作用是让程序能够通过IAT找到和调用这些函数。

weixin_32312889的博客 914

LoadRunner 回放脚本 出现ole32.dll模块故障 的处理方式

一开始出现这个错误以为是与其他软件的冲突,所以重启了电脑 问题依旧没解决 问题可能出在了loadrunner本身,然而重装了以后依旧报错。 百度了之后,有其他人在使用ie的时候出现同样问题 意识到脚本运行时启动了自带的浏览器记录运行过程,那就可能和ie的设置有关系 所以依照以下步骤进行处理 1. 关闭所有Internet Explorer窗口。 2. 单击开始,在搜索框内输入inetc...

cobbQiao的博客 1709

延迟加载库 DelayLoadHook.zip

延迟加载库 DelayLoadHook.zip

delay load深入分析

延迟加载 delay load bind rebase __FUnloadDelayLoadedDLL2 __delayLoadHelper2 ImgDelayDescr

panda1987的专栏 1万+

延迟加载库 DelayLoadDemo.zip

延迟加载库 DelayLoadDemo.zip

Android启动优化之延时加载的步骤详解

主要给大家介绍了关于Android启动优化之延时加载的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

延迟导入DLL 自定义加载行为

延迟导入DLL 自定义加载行为

lif12345的专栏 460

HTB Attacking GraphQL Skills Assessment

通过枚举应用,利用GraphQL API,发现sql注入点,然后利用找到flag。

qq_33522010的博客 453

Android性能优化 -- 应用启动优化之DelayLoad

对于应用启动优化,其实核心思想就是在启动过程中少做事情,具体实践的时候无非就是下面几种:     1. 异步加载;     2. 延时加载;     3. 懒加载。     我们这篇博客主要学习一下一种延时加载(DelayLoad)的实现及其原理。DelayLoad的实现是非常简单的,但是原理比较复杂,其中还涉及到Looper、Handler、MessageQueue、VSYNC等。 一

Kitty_Landon的专栏 1574

antdv-<a-form>的使用

是 Ant Design Vue 中用于创建表单的组件,提供了一种结构化的方式来收集用户输入。它支持多种布局、验证、数据绑定等功能,非常适合用于处理用户输入和提交数据。

2302_81312344的博客 2619

直流电动机的建模仿真(1)他励,串励和并励电动机建模仿真

本文根据不同励磁方式的直流电动机的接线原理图,建立了相应的数学模型,然后根据与数学模型对应的等效电路以及模拟机械运动方程的等效电路,用Matlab/simulink中的SpecializedPower system库中的电路元件,建立了他励,并励和串励直流电动机的全等效电路仿真模型,经过与Matlab自带的直流电动机仿真模型比较以及仿真实例验证,所建立的仿真模型时完全正确的。

weixin_45670943的博客 7519

计算机组成原理-流水线技术学习笔记1

一,处理器性能公式程序运行的时间=程序中的指令数×一条指令需要的周期数×每个周期所需的时间每条指令所需的周期数(Cyclesperinstructions,CPI),取决于ISA和处理器架构µarchitecture每个周期所需的时间,取决于处理器架构以及基础工艺basetechnology二,RSIC中的五级流水线。.........

DayDayUp 8138

ARM CoreSight架构

CoreSight架构是现代复杂SoC的“飞行数据记录仪”(黑匣子)和“精密诊断仪”的结合体。它彻底改变了嵌入式系统的调试方式,从传统的“盲人摸象”变成了拥有“上帝视角”,是ARM生态系统能够支撑起从微控制器到高性能服务器芯片如此广泛产品线的重要基石技术之一。

guigenyi的专栏 1422

利用DelayLoad来优化应用程序的性能,拦截API.

利用DelayLoad来优化应用程序的性能,拦截API.     在 1998年12月的MSJ出版刊物中, Jeffrey和我写了关于 在 vc6中使用DelayLoad 功能的专栏.最终结果,是证明了它是多么cool.但是,不幸的是,还有很多人不了解DelayLoad,他

修养生息,以得佳境 1013

Unity AssetBundle 之 (入门)简单的资源打包成AB包的方法

Unity AssetBundle 之 (入门)简单的资源打包成AB包的方法 目录 Unity AssetBundle 之 (入门)简单的资源打包成AB包的方法 一、简单介绍 二、实现原理 三、注意事项 四、效果预览 五、实现步骤 六、关键代码 一、简单介绍 Unity中的一些基础知识点。 本节介绍,Asset Bundle 在 Unity中的使用,入门第一篇,如何AssetBundle标记,如何打包成AssetBundle的操作方法,有不对的地方欢迎指正。...

仙魁XAN 1万+

海思芯片YOLOv8模型部署完整指南:从RPN硬化到8bit量化精度优化

本文详细介绍了在海思芯片平台部署YOLOv8目标检测模型的完整方案,重点解决8bit量化精度损失问题。通过分析海思RPN硬化层的性能优势(1.9ms推理时间),对比不同量化策略(16bit仅损失0.6AP,8bit损失5.2AP),并深入定位到strides计算层是量化误差的主要来源。关键突破在于采用混合精度策略(敏感层16bit,其余8bit),使8bit量化AP回升4.1%,同时保持3.4ms的推理速度和60%的低NPU占用率。文章还提供了量化参数调整、校准数据集优化等进阶技巧,为边缘计算应用提供了性能

FJN110的博客 732

运用DelayLoad来优化运用程序地性能,拦截API(转)

运用DelayLoad来优化运用程序地性能,拦截API(转) (2009-03-10 21:29:59) 转载▼ 标签: 电脑 根区 dll 函数 api it   在 1998年12月的MSJ出版刊物中, Jeffrey和我写了关于在 vc6中使用DelayLoad 功能的专栏.最终结果,是证明了它是多么cool.但是,不幸的是

autumn20080101的专栏 795

Android实战——白天黑夜模式设置

白天黑夜模式是一种动态的UI模式,根据当前时间或用户设置的偏好,在白天和黑夜之间进行切换。它通过调整应用程序的颜色、亮度和其他可视化元素来提供更加舒适和易读的用户界面。

小旭的专栏 5229

Windows平台DLL加载机制全解析与实战指南

动态链接库(DLL)是Windows平台实现代码模块化的核心技术,其加载机制直接影响应用程序的性能与稳定性。从原理上看,DLL通过导出函数表实现代码共享,采用引用计数管理生命周期。在工程实践中,开发者需要掌握静态加载、动态加载和延迟加载三种方式的技术特点:静态加载通过导入表实现自动依赖解析,动态加载则通过LoadLibrary/GetProcAddress提供运行时灵活性,而延迟加载则能平衡启动性能与模块化需求。典型应用场景包括插件系统开发、多语言互操作(如Python通过ctypes调用DLL)以及性能敏

angw337679452的博客 370

FM1288回声消除芯片调试方案 - 综述

专栏文章概览

优快云mianfeixiazai001的博客 1714

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【DLL】【学习笔记】(三)延迟加载

DLL 延迟加载

此地无银 1498

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

谈谈模块的delay load

DLL的delay load,即延迟加载,是一项提高程序启动速度,减少进程地址空间的重要技术,用通俗一点的话来讲,就是对模块“呼之即来,挥之即去”的能力。很多程序缺乏这种灵活性,从而导致软件在第一次启动时需要加载所有可能需要的模块,严重影响了启动速度。狭义的delay load,是微软提供的一项技术,让模块在其symbol第一次被引用到时才被加载。但在广义上,我们其实有不少其他技术来实现这种“需要...

weixin_34376562的博客 432

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

android 程序延迟执行一次,Android应用启动优化:一种DelayLoad的实现和原理

0. 应用启动优化概述在 Android 开发中,应用启动速度是一个非常重要的点,应用启动优化也是一个非常重要的过程.对于应用启动优化,其实核心思想就是在启动过程中少做事情,具体实践的时候无非就是下面几种:异步加载延时加载懒加载不用一一去解释,做过启动优化的估计都使用过,本篇文章将详细讲解一下一种延时加载的实现以及其原理.其实这种加载的实现是非常简单的,但是其中的原理可能比较复杂,还涉及到Loop...

weixin_35929851的博客 447

DLL 延时加载

1. exe加载多个dll时,初始化可能会比较慢 2. exe加载老版本dll时,如果没有相应的导出函数,exe可以做相应处理后继续执行。   局限性 1)导出全局变量不能延迟。 2)kernel32.dll 不能延迟, LoadLibrary and GetProcAddress 3) 不能在dllmain中调用延迟加载的函数。   onedll.dll project //o

零点起步 1194

编译器选项

将msdn上vs2013的编译器选项记载一下,我不创造文章,我只是大自然的搬运工: 1./STACK(堆栈分配) /STACK:reserve[,commit] /STACK 选项设置堆栈的大小(以字节为单位)。此选项仅在生成 .exe 文件时使用。 该选项指定虚拟内存中的总的堆栈分配。默认堆栈大小为 1 MB。链接器将指定值向上舍入为最接近的 4 个字节。 commit...

weixin_30644369的博客 748
上一篇: Change exe code
下一篇: WINDOWS2003 查密码软件findpass2003.exe源程序
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值