您的位置:首页 > 编程语言 > PHP开发

OutputDebugString的原理及模拟源码

2010-09-28 17:26 197 查看
调试某些程序时用OutputDebugString打印,用debugview输出打印比较方便,例如windows服务程序。但debugview会输出任何windows软件程序的打印信息,如迅雷和flashget。虽然debugview提供了输出过滤功能,但每次观察其输出都要过滤也很不方便,

于是就想自己模拟实现OutputDebugString函数,然后写个对应的debugview来打印输出,这样用自己的OutputDebugString来打印用自己的debugview来输出打印就方便多了。

我封装的lib接口MyOutputDebugString和对应的Mydebugview下载地址:

http://download.csdn.net/user/woshiyipihaoma

网上早有人对OutputDebugString原理做过研究,这里我借花献佛,以下为转载。

在应用程序和调试器之间传递数据是通过一个 4KB 大小的共享内存块完成的,并有一个互斥量和两个事件对象用来保护对他的访问。下面就是相关的四个内核对象:

对象名称 对象类型
DBWinMutex Mutex
DBWIN_BUFFER Section (共享内存)
DBWIN_BUFFER_READY Event
DBWIN_DATA_READY Event
互斥量通常一直保留在系统中,其他三个对象仅当调试器要接收信息才出现。事实上 - 如果一个调试器发现后三个对象已经存在,它会拒绝运行。

当 DBWIN_BUFFER 出现时,会被组织成以下结构。进程 ID 显示信息的来源,字符串数据填充这 4K 的剩余部分。按照约定,信息的末尾总是包括一个 NULL 字节。

struct dbwin_buffer {
DWORD   dwProcessId;
char    data[4096-sizeof(DWORD)];
};


OutputDebugString() 被应用调用时,它执行以下步骤。注意在任意位置的错误都将放弃整个事情,调试请求被认为是什么也不做(不会发送字符串)。

打开 DBWinMutex 并且等待,直到我们取得了独占访问。

映射 DBWIN_BUFFER 段到内存中:如果没有发现,则没有调试器在运行,将忽略整个请求。

打开 DBWIN_BUFFER_READYDBWIN_DATA_READY 事件对象。就像共享内存段一样,缺少对象意味着没有可用的调试器。

等待 DBWIN_BUFFER_READY 事件对象为有信号状态:表示内存缓冲区不再被占用。大部分时候,这一事件对象一被检查就处于有信号状态,但等待缓冲区就绪不会超过 10 秒(超时将放弃请求)。

复制数据直到内存缓冲区中接近 4KB,再保存当前进程 ID。总是放置一个 NULL 字节到字符串结尾。

通过设置 DBWIN_DATA_READY 事件对象告诉调试器缓冲区就绪。调试器从那儿取走它。

释放互斥量。

关闭事件对象和段对象,但保留互斥量的句柄以备后用。

在调试器端会简单一点。互斥量根本不需要,如果事件对象和/或共享内存对象已经存在,则假定其他调试器已经在运行。系统中任意时刻只能存在一个调试器。

创建共享内存段以及两个事件对象。如果失败,退出。

设置 DBWIN_BUFFER_READY 事件对象,由此应用程序得知缓冲区可用。

等待 DBWIN_DATA_READY 事件对象变为有信号状态。

从内存缓冲区中提取进程 ID 和 NULL 结尾的字符串。

转到步骤 2。

这使我们认为这决不是一种低消耗的发送信息的方法,应用程序的运行速度会受到调试器的左右。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: