Потоковое локальное хранилище в режиме ядра?
Существует ли эквивалент локального потока (TLS) для драйверов режима ядра в Windows (точнее, Win32)?
Чего я пытаюсь добиться:
В конечном итоге изнутри процедуры диспетчеризации моего драйвера он может вызывать многие другие функции (может быть глубокий стэк). Я хочу предоставить некоторую контекстную информацию, относящуюся к обрабатываемому запросу. То есть у меня есть некоторая структура, указатель на которую должен быть виден во всех вызываемых функциях, без явной передачи ее в качестве параметра каждой функции.
Использование static / global не является идеальным вариантом (многопоточность, синхронизация объектов и т. Д.).
Если бы это был код пользовательского режима - очевидно, в такой ситуации можно использовать TLS. Но AFAIK нет функций режима ядра, таких какTlsGetValue
/TlsSetValue
, И это имеет смысл - чтобы эти функции работали, нужно сначала выделить индекс TLS для всего процесса. Код драйвера OTOH может быть вызван в произвольном потоке, не ограничиваясь конкретным процессом.
Однако мне на самом деле не нужнастойкий специфичное для потока хранилище. Мне просто нужно специфичное для потока хранилище для вызова функций верхнего уровня.
Я думаю, что знаю, как «реализовать» TLS, хотя и хакерским способом. Вместо выделения индекса TLS я всегда буду использовать предопределенный индекс (скажем, index = 0). В функции верхнего уровня я сохраню сохраненное значение TLS и перезапишу его нужным значением. По завершении сохраненное значение будет восстановлено.
К счастью, я знаю, как TLS реализован в Win32. ЭтоTIB
структура (информационный блок потока) для каждого потока. В каждом потоке к нему можно получить доступ используяFS:[18h]
селектор.TIB
содержит (среди прочего) массив, используемый TLS. Остальное довольно просто.
Однако я бы предпочел использовать официальный API для достижения чего-то подобного.
Существует ли официальный API режима ядра для достижения того, что мне нужно?Есть ли причины избегать того, что я планирую сделать? Я знаю, что потенциально может быть проблема с повторным входом (то есть, какой-то код вызывает меня, я перезаписываю значение TLS и затем в конечном счете вызываю исходный код, который может полагаться на TLS). Но это не возможно в моем конкретном случае?Есть ли менее грязные способы решить эту проблему?Заранее спасибо.
Постскриптум Теоретически можно использовать SEH (в котором также хранится информация для каждого потока). То есть, обернуть код верхнего уровня__try/__except
тогда, где нужна контекстная информация - поднимитепродолжимы исключение с некоторым параметром, в__except
Блок заполнить параметр контекстной информацией, а затем возобновить выполнение. И это 100% действительный программный поток, без использования недокументированных функций. Но, тем не менее, это кажется мне отвратительным занятием, не говоря уже о проблемах с производительностью.