val*_*ldo 9 windows winapi kernel thread-local-storage
Windows中的内核模式驱动程序是否存在线程局部存储(TLS)等效(确切地说是Win32)?
我试图实现的目标:
最终,在我的驱动程序的调度程序中,它可能会调用许多其他函数(可能存在深度调用).我想提供一些特定于正在处理的请求的上下文信息.也就是说,我有一些结构,指针应该在所有被调用的函数中都可见,而不是将它作为参数显式传递给每个函数.
使用static/global不是一个完美的选择(多线程,同步对象等).
如果那是用户模式代码 - 在这种情况下显然会使用TLS.但是AFAIK没有像TlsGetValue/ 这样的内核模式功能TlsSetValue.这是有道理的 - 要使这些功能工作,必须首先分配一个进程范围的TLS索引.OTOH驱动程序代码可以在任意线程上调用,不限于特定进程.
但是,我实际上并不需要持久的特定于线程的存储.我只需要一个特定于线程的存储来进行顶级函数调用.
我想我知道如何以一种黑客的方式"实施"TLS.我将始终使用预定义的索引(例如,index = 0),而不是分配TLS索引.在顶级函数中,我将保存存储的TLS值,并用所需的值覆盖它.完成后,将恢复保存的值.
幸运的是我知道如何在Win32中实现TLS.TIB每个线程都有一个结构(线程信息块).在每个线程中,可以使用FS:[18h]选择器访问它.在TIB包含(除其他外)通过TLS使用的阵列.其余的非常简单.
但是,我更愿意使用官方API来实现类似的功能.
提前致谢.
PS One理论上可以使用SEH(也存储每线程信息).也就是说,包装顶级代码__try/__except,然后在需要上下文信息的地方 - 用一些参数引发可持续异常,在__except块中用上下文信息填充参数,然后恢复执行.这是一个100%有效的程序流程,不使用未记录的功能.但对我来说这似乎是一个丑陋的黑客,更不用说性能并发症了.
而不是使用FS:[18h]你应该使用PsGetCurrentThreadTeb.即便如此,我认为您将依赖可能在未来的OS版本中发生变化的细节(可能包括服务包).
相反,您不能使用KeGetCurrentProcessorNumber作为数组的索引,您可以在其中存储指向上下文信息的指针吗?(当然,如果您在DISPATCH_LEVEL或更高级别运行,那么您将无法意外地切换到其他处理器.)
如果不能保证在DISPATCH_LEVEL上运行,则可以使用表或链表,每个条目(表示当前正在运行代码的线程)标记为PsGetCurrentThread的值.
小智 5
不要用TEB这么做!TIB和TEB是用户模式结构。在驱动程序运行时,用户模式应用程序可以从另一个线程/处理器随意修改这些内容。这将是驱动程序中的特权升级漏洞。
我建议您为与您的请求相关的短暂上下文传递上下文结构。如果需要更永久的东西,可以使用AVL表或哈希表,在线程退出时进行清理。