phantom-84 писал(а):
Переключение может произойти, когда "поток пользователя" находится в режиме ядра с сильно заюзаным стеком ядра. Где хранить эти стековые данные если не в самом стеке, когда активируется другой поток?
А
зачем передавать управление другому потоку пользователя, если для первого в данный момент выполняется код ядра? Такое переключение просто должно быть отложено, и всё.
Цитата:
Одна структура потока занимает порядка 1 кб, резерв для обработчика прерывания на дне стека 2-3 кб, остается около 8 кб - с учетом многоуровневой обработки прикладных запросов в ядре это не так уж и много.
А зачем нужна эта "многоуровневая обработка прикладных запросов"? Лишние переключения туда-сюда (с одного потока на другой, с обработки запроса от одного потока на обработку запроса от другого потока и потом опять к обработке первого и т.д.) влекут за собой лишние накладные расходы: меньше времени остаётся на действительно продуктивную работу, растёт расход памяти (поскольку тогда действительно много что нужно хранить)... ИМХО, это принципиально порочный путь.
Кстати говоря, а зачем такая большая ("порядка 1 кб") структура потока? Или поток -- это не поток в смысле Вындовз, а что-то более широкое? У меня сейчас блок управления потоком имеет размер до 32 слов (128 байт, у ARMа слово -- 4 байта), блок управления задачей (в общем, примерно тем же, что в Винде называется процессом) -- до 14 слов (56 байт). Правда, пока никакой виртуальной памятью и не пахнет (система должна работать на множестве различных процессоров, и наличие MMU отнюдь не гарантировано, поэтому имеются гибкие настройки, что включать в систему, а что не включать; работаю, естественно, над тем, что мне реально нужно в ближайшее время, и виртуальная память в это число не входит), как нет пока и многопользовательской защиты. Их наличие, естественно, увеличит размеры управляющих блоков, но не в несколько раз, а на несколько слов (другое дело, что таблицы переадресации займут кучу места, но мы ж не про них говорим).
Цитата:
К тому же речь шла прежде всего о том, как управлять стеками ядра и в частности резервировать под них пространство. Я сейчас использую непрерывную область пространства ядра (глобальной ее части) и отображаю в него стеки всех существующих потоков, хотя другие системные таблицы у меня обычно фрагментированы и распределяются по всей куче ядра. Возможны и более эффективные варианты в плане экономии пространства, к примеру можно отображать стек в одну и ту же область пространства ядра при активации соответствующего потока, а учет памяти, занятой под стеки, вести с помощью гораздо более компактных структур.
Ещё раз повторюсь: стеки для потоков в режиме ядра -- неэффективная роскошь, не дающая реально никаких преимуществ. Даже если обработку запроса от потока надо прервать (например, для её продолжения требуется подгрузить с диска какую-либо страницу памяти потока), можно и нужно все необходимые для обработки запроса данные хранить в отдельной структуре данных, связанной с этим потоком. Если всё грамотно организовано, размер этой структуры будет мизерным (не больше пары-тройки десятков байт). Единственное, что здесь может мешать, -- это необходимость манипуляций со стеком режима ядра, что на языке высокого уровня выполнить невозможно. Однако поддержка всех этих манипуляций требует всего нескольких небольших подпрограмм на ассемблере да соблюдения определённой дисциплины при программировании остальной части системы.