标签: windows-kernel

实现实时 1 毫秒精确事件而不受线程调度的影响

问题

我正在使用.Net 4.5创建一个基于 Windows 7 的 C# WPF应用程序,它的一个主要功能是调用某些函数,这些函数与具有一组用户定义的循环时间的自定义硬件接口。例如,用户可能会选择每 10 或 20 毫秒调用两个函数以及每 500 毫秒调用另一个函数。用户可选择的最小循环时间为 1 毫秒。

起初,时间似乎是准确的,并且根据需要每 1 毫秒调用一次函数。但是我们后来注意到大约1-2%的时间是不准确的,有些函数被调用只延迟了 5 毫秒,而其他函数可能会延迟到 100 毫秒。即使循环时间大于 1 毫秒,我们也面临线程休眠的问题,它应该调用外部函数(一个 20 毫秒的函数可能会延迟 50 毫秒调用,因为线程正在休眠并且没有调用该函数)

经过分析,我们得出结论,这些延迟是零星的,没有明显的模式,这些延迟背后的主要原因可能是操作系统调度和线程上下文切换,换句话说,我们的线程并没有像我们需要的那样一直处于唤醒状态.

由于 Windows 7 不是 RTOS,我们需要找出是否可以以某种方式解决此问题。但我们确实知道这个问题在 Windows 上是可以解决的,因为我们使用其他具有类似功能的工具,可以满足最大 0.7 ms 容错的时序约束。

我们的应用程序是多线程的,最多同时运行 30 个线程,其当前 CPU 使用率峰值约为 13%

尝试的解决方案

我们尝试了很多不同的东西,主要是使用秒表计时器测量计时,并且IsHighResolution为 true(使用了其他计时器,但我们没有注意到太大差异):

  1. 创建一个单独的线程并赋予它高优先级
    结果:无效(使用可怕的Thread.Sleep(),没有它并使用连续轮询)

  2. 使用 C# 任务(线程池)
    结果:改进很小

  3. 使用 1ms 周期的多媒体定时器 …

c# windows multithreading rtos windows-kernel

7
推荐指数
1
解决办法
6484
查看次数

如何从内部卸载Windows内核模式驱动程序?

我正在编写一个 Windows 内核驱动程序,并尝试实现以下内容。

假设已通过DeviceIoControl函数使用特定的 IOCTL 代码从用户模式调用驱动程序。在这种情况下,驱动程序如何自行卸载?换句话说,如何实现与运行net stop命令相同的行为?

更准确地说,在实现DispatchDeviceControl 回调时我应该写什么

NTSTATUS IoctlDeviceControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) {
    // some code...

    switch (ioctlCode) {
        case IOCTL_MY_UNLOAD:  <---
        ...
    }

    return Status;
}
Run Code Online (Sandbox Code Playgroud)

windows kernel driver windows-kernel

6
推荐指数
1
解决办法
4308
查看次数

Windows CPU Scheduler - 内核时间非常长

我们正在尝试了解Windows CPU Scheduler如何工作以优化我们的应用程序,以实现最大可能的基础架构/实际工作比率.在xperf中有一些我们不理解的东西,并且想要让社区了解真正发生的事情.当我们得到一些服务器"缓慢"或"无响应"的报告时,我们最初开始调查这些问题.

背景资料

我们有一台运行我们的中间件基础架构的Windows 2012 R2 Server,其规格如下.

我们发现有30%的CPU浪费在内核上,所以我们开始深入挖掘.

任务管理器视图

上面的服务器运行"主机"~500个进程(作为windows服务),这些"主机"进程中的每一个都有一个内部while循环,延迟〜250毫秒(yuck!),并且每个"主机"进程可能有〜 1..2执行实际工作的"子"进程.

虽然在迭代之间具有250毫秒延迟的无限循环,但"主机"应用程序执行的实际有用工作可能仅每10..15秒出现一次.所以浪费了很多周期来进行不必要的循环.

我们知道,"主机"应用程序的设计至少可以说是次优的,适用于我们的场景.应用程序将更改为基于事件的模型,该模型不需要循环,因此我们期望CPU利用率图中的"内核"时间显着减少.

然而,当我们调查这个问题时,我们已经做了一些xperf分析,它提出了几个关于Windows CPU Scheduler的一般性问题,我们无法找到任何明确/简明的解释.

我们不明白的是什么

以下是其中一个xperf会话的屏幕截图.

xperf会话

您可以从"CPU使用率(精确度)"中看到

  • 有15毫秒的时间片,其中大部分未充分利用.这些切片的利用率约为35-40%.因此,我认为这反过来意味着CPU大约在35%到40%的时间内被利用,但系统的性能(假设通过系统周围的随意修改可观察到)实际上是缓慢的.

  • 有了这个,我们就有了这个"神秘的"30%内核时间成本,由任务管理器CPU利用率图判断.

  • 有些CPU明显用于整个15 ms及更高的分片.

问题

就多处理器系统上的Windows CPU调度而言:

  • 什么导致30%的内核成本?上下文切换?别的什么?在编写应用程序以降低此成本时应该考虑哪些因素?甚至 - 以最小的基础设施成本实现完美的利用(在多处理器系统上,其中进程数高于核心数)
    • 这些15毫秒切片是什么?
    • 为什么CPU利用率在这些切片中存在差距?

windows performance context-switch xperf windows-kernel

6
推荐指数
1
解决办法
3900
查看次数

发现加载和卸载内核模式驱动程序的足迹

背景:Windows 系统存在易受攻击的内核模式驱动程序,可以出于各种目的将其加载到系统中。加载的内核模式驱动程序会在系统中留下痕迹。例如,视频游戏的反作弊软件会在系统的各个部分寻找易受攻击的驱动程序痕迹,因为它们被用于作弊。反作弊软件使用的逻辑可能(或已经)被反 rootkit 工具或 rootkit 本身使用。

我想知道驱动程序加载然后卸载后留下的痕迹。通过我的研究,我在Windows NT内核中发现了这两个地方,卸载的驱动程序会留下痕迹:

  1. PiDDB缓存表
  2. 卸载驱动程序

(只是让你知道,那些是未记录的数据结构)他们还能在哪里留下痕迹?我是否可以在不自己对 Windows 内核进行逆向工程的情况下学习它?

windows nt windows-kernel

6
推荐指数
1
解决办法
274
查看次数

如何判断Windows内核事件对象是自动重置还是手动重置?

Windows允许创建(命名)事件对象.

一个事件(Windows中的同步原语)可以是自动重置类型(在这种情况下你可以说它是一种信号量)或者它可以是手动重置类型,在这种情况下它会保持设置直到有人重置它.

现在,从文档CreateEvent,OpenEvent,SetEvent的,等它似乎是没有办法确定,一旦事件已经创建,无论是自动复位或maual复位.

我处于这种情况,其中一个进程创建一个命名的事件,第二个进程必须对此事件进行操作(它将传递名称,然后打开事件并最终发出信号).由于事件应始终是手动重置事件,因为整个事情都有意义,我本来希望在第二个过程中添加一个检查以确保它一个手动重置事件.有没有办法检查这个?

(是的,在我的情况下,它更像是一个很好的东西,因为如果任何代码创建一个自动重置事件然后将它传递给这个过程,那么它将是一个错误.但是错误发生了,如果发生了错误,那就更好了.我可以发现它们.)

windows winapi manualresetevent autoresetevent windows-kernel

5
推荐指数
1
解决办法
505
查看次数

windows设备驱动程序中pdo和fdo有什么区别?

我正在研究自己的Windows设备驱动程序,我发现很难区分PDO和FDO.让我告诉你,如果我错了,我头脑中的流量会纠正我!

系统启动时,它会加载将创建FDO的根总线驱动程序.现在它将枚举其子设备,并且我想在将找到一个新的子项并且该方法将通知PNP管理器时将调用总线驱动程序的一些热插拔方法.PNP管理器将调用根总线驱动程序的AddDevice()例程,并将为新总线创建PDO,如PCI等等.请详细解释整个流程,这只是我的想象.然后记录系统将加载PCI总线的功能驱动程序,这将创建FDO ?? 这个FDO是什么?为什么我需要那个?根据我的说法PCI总线驱动程序也应该遵循与根总线相同的操作,枚举其子节点并为它们创建PDO,或者通过这个FDO它们仅意味着PDO?我很困惑:( !!

windows windows-kernel

5
推荐指数
2
解决办法
7680
查看次数

Windbg条件断点,在嵌套结构中使用字符串比较

只有当嵌套结构中的字符串作为参数匹配我选择的特定模式时,我一直试图在函数内部触发断点,如下所示:

bp `main.c:2236` ".block { .if ( $spat(\"@@(stNames->NameComponent.Buffer)\", \"*ab*\" )){.echo \"BKP HIT! \"; .printf \"%mu str\n\",> @@(NameInfo->FinalComponent.Buffer); } .else {.echo \"NO HIT \"; .printf \"%mu str:\n\", @@(stNames->NameComponent.Buffer); gc;} } "
Run Code Online (Sandbox Code Playgroud)

在已经解析参数符号之后,此断点设置在函数的开头.它表现得很奇怪,即使$ spat中的模式不匹配,有时它也会一直被击中,有时即使模式匹配也不会命中.

我也试过这个没有运气,因为我无法找到一个方法在嵌套结构的这种情况下使用POI()命令.片段波纹管:

bp Kernel32!CreateFileW ".printf \"%mu\\n\", poi(esp+4); as /mu ${/v:FileName} poi(esp+4); .block{.if $spat(\"${FileName}\", \"*target*\") {.echo Hit} .else {.echo Not Yet;g;}}"
Run Code Online (Sandbox Code Playgroud)

c windbg windows-kernel

5
推荐指数
1
解决办法
2951
查看次数

WinForms 深层嵌套控件调整内核大小错误 - 拆分面板无法正确缩放控件

(对nested 的初步猜测被证明是不正确的。问题似乎是SplitContainer 面板没有正确缩放其托管控件。)


我有一些表单的选项卡控件在加载时无法正确调整大小。 https://support.microsoft.com/en-us/kb/953934在 2008 年描述了这样一个内核错误。很难相信它没有得到修复。我认为它消失了一段时间,但我又开始看到问题了。

控件嵌套得很深。Midi 父、子窗体、选项卡控件、带有两个面板和控件的拆分器控件。对于自上而下的第一个有问题的控件是选项卡控件。当加载后调整窗体大小但锚点不正确并且部分控件被剪切时,它会调整大小。

该问题似乎特定于 100% 桌面字体大小 - 100+ 大小的桌面工作正常。我使用 VS 2013 v5 以 125% 的速度开发 - 这个问题也出现在 v4 上。

任何人都知道缺少知识库文章中概述的自定义控件的解决方法吗?

我错过了其他事情?


仔细观察 SplitContainer 是不调整锚点大小/尊重锚点的控件。


我尝试在显示选项卡后运行此代码但它不起作用 - 看起来与使用锚点大致相同。似乎 TabControl 报告的 ClientSize 不正确

    SplitContainer1.Width = TabControl1.ClientSize.Width - 10
    SplitContainer1.Height = TabControl1.ClientSize.Height - TabControl1.ItemSize.Height - 10
Run Code Online (Sandbox Code Playgroud)

这是显示问题的完整表格。在 125% 桌面上,它显示为在 100% 桌面上的 IDE 中,选项卡上的控件未正确定位。

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class frmChild
Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing …
Run Code Online (Sandbox Code Playgroud)

vb.net winforms windows-kernel

5
推荐指数
1
解决办法
1094
查看次数

Windows 7内核模式下如何设置内存区域保护

本质上,我正在寻找一个可以为内核模式做什么的函数,它可以VirtualProtect为用户模式做什么。

我正在使用以下简化代码示例的逻辑分配内存。

    PMDL mdl = MmAllocatePagesForMdl    
    (
        LowAddress,
        HighAddress,
        SkipAddress,
        size
    );

    ULONG flags = NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite;
    PVOID ptr = MmGetSystemAddressForMdlSafe
    (
        mdl, 
        flags
    );
Run Code Online (Sandbox Code Playgroud)

MdlMappingNoExecuteMdlMappingNoWrite标志只会对Win8的+效果。
此外,仅使用MmGetSystemAddressForMdlSafeI 无法NoAccess为内存区域分配例如保护。

是否有任何额外的或替代的 API-s 我可以使用,以便我可以修改分配内存的页面保护?
hack 也可以,因为目前此功能不会在生产代码中使用。

memory-management windows-kernel

5
推荐指数
1
解决办法
3557
查看次数

除非我禁用/启用我的设备,否则 CreateFile 会失败

更新(在底部)

我有一个基于 IddCx 示例的 UMDF 视频驱动程序。我有一个命令行测试(以“管理员CreateFile身份”运行),它调用视频适配器设备实例以获取用于 IOCTL 目的的句柄。在访问被拒绝CreateFile呼叫中测试失败

我发现如果我只是在设备管理器中禁用并重新启用适配器,然后重新运行相同的测试,它就会成功。测试将继续成功,直到我重新启动 Windows,或卸载/重新安装设备。

测试的CreateFile调用本身不会触发对我的驱动程序的任何调用(更多内容见下文),因此我无法轻松自下而上地对其进行调试。

切换适配器设备的激活状态改变SOMETHING使得完全相同的CreateFile调用成功。我决定跟踪CreateFile调用直到它失败......这是我发现的:

--- User Mode ---
mytest!CreateFile
ntdll!NtCreateFile
--- Kernel Mode ---
nt!IopCreateFile
nt!ObOpenObjectByNameEx
nt!ObpLookupObjectName
nt!IopParseDevice
nt!SeAccessCheck [returns Access Denied]
Run Code Online (Sandbox Code Playgroud)

nt!IopParseDevice调用nt!SeAccessCheck,当它返回时FALSEnt!IopParseDevice将最后一个错误设置为拒绝访问并返回失败。

现在,这是有趣的部分(我需要帮助):

传入的参数nt!SeAccessCheck略有不同,具体取决于我是禁用+启用设备之前还是之后运行测试。值得注意的是,提供的 SecurityDescriptor 参数的SECURITY_DESCRIPTOR_CONTROL成员发生了变化:

(after Windows restart or adding new …
Run Code Online (Sandbox Code Playgroud)

winapi driver internals wdk windows-kernel

5
推荐指数
0
解决办法
178
查看次数