0

在我的程序结构中,我将“调用它的位置”和“完成了什么”划分为单独的源文件。作为实用性问题,这允许我将程序作为独立程序编译或将其包含在 DLL 中。下面的代码不是实际代码,而是一个简化的示例,说明了同样的问题。

这里有 3 个交互组件:加载我的 DLL 的内核模式程序、DLL 及其源文件以及带有它的源的实用程序,它们是单独维护的。

在 DLL 形式中,程序作为线程加载。根据内核模式应用程序供应商的文档,我失去了在内核程序初始化后调用 Win32 API 函数的能力,因此我将线程加载为活动线程(而不是使用 CREATE_SUSPENDED,因为我无法唤醒它)。

我让它监视一个标志变量,以便它知道何时通过一个不优雅但功能强大的东西做一些有用的事情:

while ( pauseThreadFlag ) Sleep(1000);

最多 1 秒的延迟是可以接受的(整个过程很长,而且很少调用),并且似乎不会影响系统。

在线程源文件中,我将变量声明为

volatile bool pauseThreadFlag = true;

在我声明的 DLL 源文件中

extern volatile bool pauseThreadFlag;

当我准备好执行线程时,在我设置的 DLL 中

pauseThreadFlag = false;

我在将 std::string 对象声明为 volatile 时遇到了一些困难,因此我将参数声明为线程源文件中的全局变量,并让 DLL 调用设置器驻留在线程源中。如果我可以随意实例化线程,这些字符串将是参数。

(所有这一切都缺少锁定变量以确保线程安全,这是我的下一个“要做的事情”)

这让我觉得这是一个糟糕的设计......它的功能性但令人费解。鉴于我提到的限制,有没有更好的方法来解决这个问题?

我在想一个可能的修改是使用在线程创建时给出的 LPVOID lpParams 变量来保存指向字符串对象的指针,即使创建线程时字符串是空的,并且直接从线程访问它们,这样完全删除线程程序中的声明、设置器等?如果这可行,那么也可以在那里引用暂停标志,并消除外部声明(但我认为它仍然需要声明为 volatile 以提示优化器)。

如果有任何区别,环境是 Visual Studio 2010、C++、目标平台 Win32 (XP)。

谢谢!

4

2 回答 2

1

如果所有组件都在内核模式下运行,您将需要查看KeInitializeEventKeSetEventKeResetEventKeWaitForSingleObject。这些都以与其等效的用户模式类似的方式工作。

于 2011-07-20T21:31:49.743 回答
0

我最终删除了该结构并将其替换为一个封装所有数据的对象。这有点可怕,充满了 getter 和 setter,但在这种特殊情况下,我使用访问方法来确保正确设置/取消设置锁。

使用指向该对象的 void 强制转换指针正确地传递了该对象,并且看起来相当稳定。

于 2011-07-26T14:19:06.453 回答