ZarathustrA писал(а):
Вы не учитываете, того факта, что РТ-системы должны передавать задаче управление сразу же по возникновению определенного события (прерывание, освободился ресурс и т.д.). В том числе это должно происходить и при выполнении кода ядра ОС. Поэтому например Линукс не является РТ-системой, именно потому что его ядро не является реентерабельным и любая РТ-задача будет ожидать завершения выполнения системого вызова неопределенной продолжительности теоретически стремящейся к бесконечности, что в свою очередь ставит крест на предсказуемости...
Вы ошибаетесь. Во-первых, система реального времени не должна "передавать задаче управление сразу же по возникновении определённого события" -- она должна это делать за _предсказуемое время_, а не мгновенно. Что это так, понятно из простого примера. Предположим, пришёл сигнал о том, что в управляемом Вашей системой ядерном реакторе возникли серьёзные проблемы с самим реактором, и его нужно срочно глушить. Естественно, управление получает задача, отвечающая за аварийный останов реактора. Вскоре после этого (останов ещё не выполнен) приходит другой сигнал: обнаружено нарушение работы вентилятора, охлаждающего лысину главного инженера станции. Проишествие, конечно, страшное, но реакция на него вполне может быть отложена до тех пор, пока до конца не отработает задача глушения реактора. Следовательно, управление передаётся не сразу, важно лишь, чтобы это время можно было предсказать и оно ни в какой ситуации не вышло за допустимые рамки.
Вторая ошибка заключается в том, что событие непременно должно обрабатываться задачей. Например, в случае оси с монолитным ядром глушение вышеупомянутого реактора по прерыванию от его схем контроля инициировалось бы драйвером режима ядра, обрабатывающим это прерывание -- как раз с тем, чтобы принять меры как можно быстрей, и лишь дальнейшая обработка, не требующая столь срочных мер, была бы переложена на обычные задачи (грубо говоря, уронить аварийные стержни нужно сразу же по поступлении сигнала об аварии, а сообщить об этом оператору можно и через 10 мс -- всё равно время реакции человека слишком велико).
Ну а что касается линуха, то проблема как раз в непредсказуемости, а не в реентерабельности ядра. Ядро может быть нереентерабельным, но с чётко предсказуемым временем реакции (конечно, на конкретном круге задач и с конкретным оборудованием -- но настоящие системы реального времени именно так и строятся, да и сертифицируется не сама ось, а весь программно-аппаратный комплекс). Та же упомянутая мной RSX-11 является системой жёсткого реального времени, однако её ядро нереентерабельно в том смысле, что нельзя начинать обработку следующего отложенного прерывания до окончания обработки предыдущего. Просто все действительно суперсрочные действия делались в драйверах, а остальное -- в задачах, время получения управления которыми было легко прогнозируемым. Правда, на практике как управляющую обычно использовали RT-11, не имеющую многозадачности вовсе или же поддерживающую 2 или 3 задачи в зависимости от конфигурации: она, понятное дело, была компактнее и работала быстрее, что для железа начала 1970-х было очень критичным, однако бывали и случаи, когда работала именно RSX-11 (у неё даже специальный управляющий вариант был -- RSX-11S).
Кстати говоря, у линуха как раз по одному стеку ядра на каждый поток пользовательского режима -- что её, однако, не делает ОСРВ, да к тому же приводит к дикому лишнему расходу памяти.
SII писал(а):
Давайте прикинем: 1) системный вызов -> прерывание IPI -> прерывание первого уровня -> прерывание второго уровня -> прерывание таймера
2) исключение -> double fault -> прерывание IPI -> прерывание первого уровня -> прерывание второго уровня -> прерывание таймера
При этом обработчики прерывания достаточно просты в расчете, а вот вариантов обработки системных вызовов и исключений значительно больше, поэтому максимально необходимый им размер стека просчитать сложнее.
Что расчёт не является _абсолютно элементарным_, я спорить не буду: так и есть. Но, если в ядро не напихано всё подряд, а само оно достаточно нормально спроектировано, то его сложность остаётся в разумных пределах, и просчитать максимально потребный объём с точностью до байта вполне реально.
ZarathustrA писал(а):
Однако, я считаю большим достоинством архитектуры AMD64 то, что она позволяет вести раздельные стеки прерываний и системных вызовов. Это автоматически и наиболее элегантно решает поднятую проблему.
Знаете, в архитектуре АРМ тоже имеет место разделение. И лично для меня оно оказалось крайне неудобным. Другое дело, что я делаю монолитное ядро, а в Вас вроде микроядро (не люблю я их: теоретические преимущества, конечно, есть, но я не считаю их столь важными, чтобы искупить недостатки в виде усложнения системы в целом и сильной потери производительности).