Прочитал в статье, соответствующей курсу лекций одного технического ВУЗа, высказывание следующего содержания: Я хотел бы прояснить для себя данное утверждение, уточнить - верно оно или нет, а если да - как со стороны операционной системы обеспечивается неповторновходимость? Если код выполняется в режиме ядра на уровне PASSIVE_LEVEL - он может быть прерван. Если после этого в результате передиспетчеризации начнет выполняться другой поток, находившийся в режиме пользователя, он ведь продолжит выполнение в режиме пользователя? Тогда он может войти в режим ядра => повторновходимость? Или при выполнении в режиме ядра, поток не может быть прерван для выполнения кода в режиме пользователя? Что в этом случае следует понимать под "правами на контекст ядра"?
Возможно автор имеет ввиду чуть другое. Когда ты делаешь sysenter ты попадаешь в Kernel Mode но не контекст ядра. Даже в ядре ты остаешься в контексте процесса который вызвал код. Другое дело - когда загружаешь драйвер. Тогда ты попадаешь в контекст ядра. Тогда хз каким образом пашут потоки ядра
В принципе это утверждение верно... Но для старых версий Linux. Там ядро было non-reentrant. Есть предположение, что автор статьи не понимает о чем пишет.
Судя по терминам. речь про НТ. Там ядро переключаемо. Любой поток, выполняющийся на процессоре с IRQL <= APC_LEVEL. конечно да. для синхронизации используются спин-блокировки. автор курил))
Забавно, "Ядро не повторновходимо". Речь о реентерабельности кода, как я понимаю. Другими словами, может ли один и тот же код в ntoskrnl выполняться в нескольких потоках одновременно и не будет ли при этом возникать рассинхронизации. Кончено может выполняться. К сожалению, наши ВУЗы имеют весьма скромное представление об NT.
Повторно входимо. Из трап-фреймов цепочки формируются. Как пример - механизм теневых калбэков. Специально для этого введено понятие базового трап-фрейма, это тот который самый первый. Далее цепочка может формироваться по разным причинам - это прерывания, либо програмные механизмы.
А вот теневые колбеки – это, как нам кажется, не совсем удачный пример. Потому что ядерная часть древней графической подсистемы винды как раз НЕ реентерабельна. Захотелось сделать окошко видимым? Вызываем ShowWindow() и попадаем в ядро на NtUserShowWindow(), где эксклюзивно захватывается сессионно глобальный лок. Другому потоку, совершенно не связанному с первым, нужно в этот момент, скажем, удалить пункт меню? Он вызывает DeleteMenu() и оказывается в ядре на NtUserDeleteMenu(), где вынужден ждать, пока сессионный лок освободится. Первому потоку, выполняемому в ядре, понадобилось сделать колбек в юзермод? Отлично, на время выполнения юзермодного кода лок освобождается – но по возращению в ядро нужно будет снова его захватить. Т.е. в этом плане получаем именно нереентерабельную систему. (Иначе при этой кодобазе, берущей начало ещё в Win16, поступать попросту невозможно). Но, конечно, в ntoskrnl – как уже сказали – такого чудовищного по современным меркам механизма не применяется.
Sol_Ksacap Пример удачный. Например понижаете в IRQL до нулевого и размаскируете прерывания, состояние задачи уже сохранено, тогда при приходе железячного прерывания вновь текущее состояние задачи сохраняется, после отработки ISR задача будет возобновлена. Иначе был бы не возможным вложенный трап-процессинг.
Кстате очень многим не понятны конструкции типа такой: Код (Text): TrapFrame = (PKTRAP_FRAME)((PUCHAR)Thread->InitialStack - ALIGN_UP(sizeof(KTRAP_FRAME),KTRAP_FRAME_ALIGN) - sizeof(FX_SAVE_AREA)); Изза возможной вложенности задач всегда используется первый её контекст, лежащий на дне ядерного стека.