内核模式下的线程本地存储? [英] Thread-local storage in kernel mode?

查看:101
本文介绍了内核模式下的线程本地存储?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Windows(确切地说是Win32)中,是否存在与内核模式驱动程序等效的线程本地存储(TLS)?

Is there a Thread-Local Storage (TLS) equivalent for kernel-mode drivers in Windows (Win32 to be exact)?

我试图实现的目标:

最终,在驱动程序的调度例程中,它可能调用许多其他函数(可能有一个深层的调用栈).我想提供一些特定于正在处理的请求的上下文信息.也就是说,我具有某种结构,该结构的指针在所有调用的函数中都应该可见,而无需将其作为参数显式传递给每个函数.

Eventually from within my driver's dispatch routine it may call many other functions (there may be a deep callstack). I want to supply some context information specific to the request being processed. That is, I have some structure, pointer to which should be visible in all the called functions, without explicitly passing it as a parameter to every function.

使用静态/全局不是一个完美的选择(多线程,同步对象等).

Using static/global is not a perfect option (multithreading, sync objects and etc.).

如果这是一种用户模式代码,则在这种情况下显然会使用TLS.但是AFAIK没有像TlsGetValue/TlsSetValue这样的内核模式函数.这很有意义-为了使这些功能正常工作,必须首先分配一个进程范围的TLS索引. OTOH驱动程序代码可以在任意线程上调用,而不仅限于特定进程.

If that was a user-mode code - one would obviously use TLS in such a situation. But AFAIK there are no kernel-mode functions like TlsGetValue/TlsSetValue. And this makes sense - for those function to work one has to allocate a process-wide TLS index first. OTOH driver code may be invoked on arbitrary thread, not limited to a specific process.

但是我实际上并不需要永久特定于线程的存储.我只需要一个特定于线程的存储即可进行顶层函数调用.

However I don't actually need a persistent thread-specific storage. I just need a thread-specific storage for my top-level function invocation.

我认为我知道如何实施" TLS(尽管采用了骇人听闻的方式).我将始终使用预定义的索引(例如,index = 0)来代替分配TLS索引.在顶级功能中,我将保存存储的TLS值,并用所需的值覆盖它.完成后,保存的值将被恢复.

I think I know how to "implement" the TLS, though in a hackish way. Instead of allocating the TLS index I will always use a predefined index (say, index=0). At the top-level function I'll save the stored TLS value, and overwrite it with the needed value. Upon completion the saved value will be restored.

幸运的是,我知道TLS是如何在Win32中实现的.每个线程都有一个TIB结构(线程信息块).在每个线程中,都可以使用FS:[18h]选择器对其进行访问. TIB包含(除其他事项外)TLS使用的数组.其余的非常简单.

Luckily I know how the TLS is implemented in Win32. There's a TIB structure (thread information block) for each thread. In every thread it may be accessed using FS:[18h] selector. The TIB contains (among other things) an array used by TLS. The rest is pretty straightforward.

但是我更喜欢使用正式的API来实现类似的目的.

However I'd prefer to use an official API to achieve something similar.

  • 是否有官方的内核模式API可以满足我的需要?
  • 是否有理由避免我打算做的事情?我知道重入可能存在问题(即某些代码调用了我,我覆盖了TLS值,然后最终调用了可能依赖TLS的原始代码).但这在我的特定情况下是不可能的吗?
  • 解决这个问题的方法更少吗?

谢谢.

P.S.从理论上讲,人们可以使用SEH(它还存储了每个线程的信息).也就是说,用__try/__except包装顶级代码,然后在需要上下文信息的地方-使用某些参数引发 continuable 异常,在__except块中,用上下文信息填充参数,然后继续执行.这是100%有效的程序流程,无需使用未记录的功能.但这对我来说似乎是一个丑陋的技巧,更不用说性能上的复杂性了.

P.S. One may theoretically use SEH (which also has per-thread information stored). That is, wrap the top-level code by __try/__except, then where the context information is needed - raise the continuable exception with some parameter, in the __except block fill the parameter with the context information, and then resume the execution. And this is a 100% valid program flow, without use of the undocumented features. But nevertheless this seems an ugly hack for me, not to mention the performance complications.

推荐答案

而不是使用FS:[18h],您应该使用PsGetCurrentThreadTeb.即使那样,我认为您仍将依赖于将来的OS版本(可能包括Service Pack)中可能更改的细节.

Rather than using FS:[18h] you should probably use PsGetCurrentThreadTeb. Even then, I think you'd be relying on details that might change in future OS releases (potentially including service packs).

相反,您是否不能使用KeGetCurrentProcessorNumber作为数组的索引,您可以在该数组中存储指向上下文信息的指针? (当然,要确保您运行的是DISPATCH_LEVEL或更高版本,这样就不会意外地切换到其他处理器.)

Instead, couldn't you use KeGetCurrentProcessorNumber as an index into an array where you can store a pointer to your context information? (Provided that you're running at DISPATCH_LEVEL or higher, of course, so that you can't be switched to a different processor unexpectedly.)

如果不能保证在DISPATCH_LEVEL上运行,可以使用表或链表,每个条目(代表当前正在运行代码的线程)都标有PsGetCurrentThread的值.

If you're not guaranteed to be running at DISPATCH_LEVEL, you could use a table or linked list, with each entry (representing a thread that is currently running your code) labelled with the value of PsGetCurrentThread.

这篇关于内核模式下的线程本地存储?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆