zoukankan      html  css  js  c++  java
  • 有关OutputDebugString的一点儿事实

    我最近花了一些时间分析OutputDebugString方法。在我的另一个实验中,我需要一个仅依赖于本机API的OutputDebugString版本。在实现它的过程中,我发现了一些关于OutputDebugString的有趣的事实,也许您也会感兴趣。

    OutputDebugString的工作原理

    简而言之,OutputDebugString尝试将消息发送到附加到给定进程的调试器,如果没有调试器侦听,则尝试将全局节映射到进程内存中并将调试消息保存在其中。我使用本机API实现OutputDebugStringA(ANSI版本)的示例如下:

    void NTAPI RtlOutputDebugStringA(_In_opt_ LPCSTR OutputString) {
        if (OutputString) {
            EXCEPTION_RECORD exceptionRecord{ 0 };
     
            exceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C;
            exceptionRecord.NumberParameters = 2;
            exceptionRecord.ExceptionInformation[0] = strlen(OutputString) + 1;
            exceptionRecord.ExceptionInformation[1] = reinterpret_cast<ULONG_PTR>(OutputString);
     
            __try {
                RtlRaiseException(&exceptionRecord);
            } __except (EXCEPTION_EXECUTE_HANDLER) {
                NotifyGlobalDebugOutputMonitor(OutputString);
            }
        }
    }

    RtlOutputDebugStringA(以及OutputDebugString)检查调试器存在的方式非常有趣:它引发了一个异常。如果有一个调试器正在侦听,它将吞了异常(异常代码:0x40010006L表示ANSI消息,0x4001000A表示UNICODE消息),并且处理程序将永远不会执行。我们都知道异常是昂贵的,我们应该只在特殊情况下使用它们。因此,对跟踪的每个写操作都抛出异常似乎不正确。稍后我将向您展示一些基准测试结果和解决此问题的简单方法(我想您已经知道了)。但是关于NotifyGlobalDebugOutputMonitor方法的前几句话。它使用一个全局映射部分、两个事件对象和一个互斥对象来编写调试消息。事件对象和互斥锁保护该节防止并发使用。我不会过多地讨论这个问题;如果你感兴趣,可以看看张玉武关于代码项目的优秀文章。您还可以在github上查看我的实现的源代码(它只是一个POC,所以请不要在接近生产的地方使用它)。可以说,在系统中运行调试输出监视器(如DebugView)也会对OutputDebugString性能产生负面影响,特别是当多个进程同时向调试输出写入数据时。

  • 相关阅读:
    IO 单个文件的多线程拷贝
    day30 进程 同步 异步 阻塞 非阻塞 并发 并行 创建进程 守护进程 僵尸进程与孤儿进程 互斥锁
    day31 进程间通讯,线程
    d29天 上传电影练习 UDP使用 ScketServer模块
    d28 scoket套接字 struct模块
    d27网络编程
    d24 反射,元类
    d23 多态,oop中常用的内置函数 类中常用内置函数
    d22 封装 property装饰器 接口 抽象类 鸭子类型
    d21天 继承
  • 原文地址:https://www.cnblogs.com/yilang/p/12038397.html
Copyright © 2011-2022 走看看