Перейти к содержанию
    

Параметры оценки архитектуры ОС

Далее, то что вы называете - таймерами, если я правильно вас понял - это просто Источники Событий некого рода.

То что вы называете прерываниями - тоже источники событий.

 

Чтобы написать( как вы спрашиваете ) ядро без запрета прерываний - нужно просто прерывания оформить в стиле источников событий. То есть физический источник события просто вкидывает Событие в некий буфер, и обозначает ассоциированную процедуру обработки или тред ожидающий события как Активный. А решедулер, затем запускает эти помеченные как активные, обьекты(треды). Это самыми общими словами. ТО есть запрет прерываний тут происходит только на этапе вбрасывания события в буфер и выборки его тредом из буфера. Чтобы источник событий и приемник - не столкнулись.

 

Иного способа написать ядро без запретов прерываний - нет.

Таймеры отличаются тем, что события в них инициализируются пользовательскими процессами, имеющими различные приоритеты и в произвольном порядке. Таким образом, допустим, мы используем некий буфер для Событий. Если физический источник События - прерывание или процесс, то мы можем выделить каждому источнику отдельный буфер и обрабатывать поступившие туда события по принципу FIFO. Если источник событий - таймер, то мы должны обеспечить сортировку Событий либо при помещении в буфер, либо при изъятии из него, это гораздо сложнее и требует запрещения прерываний на время сортировки. Существует вариант динамического выделения отдельного буфера размером один элемент каждому событию таймера (поскольку нам неизвестно их число) - тоже неясная задача.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

***но известное (т.е., например, в диспетчере: при сортировке очереди на выполнение прерывания запрещаются не на все время сортировки (которое зависит от размера очереди и поэтому не предсказуемо), а периодами - на время анализа очередного элемента (которое известно)***

 

Проблемы будут.

Например если список линейный, то если в данный момент(когда прерывания запрещены) поле next у текущего элемента имеет одно значение, то если вы прерывания разрешили, а потом опять запретили...поле next может быть уже совсем другим. а самого элемента this - может уже и не быть в очереди. Кто то его вытащил.

То есть кто-то может вам просто "оборвать" список. Это будет трудноуловимой ошибкой, поскольку получится при коллизии доступа к текущему или следующему элемента списка.

 

То есть если вы работаете с элементом - монопольно, вы не имеете права брать next от текущего элемента, запоминать и использовать его в следующем "такте" монопольной работы.

Если же вы будете думать что текущий в "такте" монопольной работы - действительно в списке(поскольку в предыдущем такте он там был!) - вас ударит с другого конца. Если его уже вытащили оттуда, его поле - next - будет nil.

Как будем выкручиваться?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если таймеры у вас в системе "жесткие", что обычно бывает в ртоc, то они реализуются так.

На аппаратном таймере сидит процедура, что запускает таймерные хуки(функции определяемые пользователем) по списку "взведенных" таймеров. Такие хуки запускаются синхронно, то есть прямо фактически из прерывания, правда перед запуском хуков прерывания от аппаратного таймера разрешаются.

Хуки не могут пытаться втстать в ожидание, поскольку синхронный код, запускаемый из прерывания не может это делать - система рухнет. Но для особо привязанных ко времени приложений, типа лампочкой попикать или в порт байты кидать - такое - работает хорошо и быстро.

 

Мягкие таймеры, для задач, когда отклонение на квант работы одного треда не играет роли - например что-то выводить на экранчик периодически юзеру...активируются из системного треда - опросчика таймеров. Он себе крутится пока очередь таймеров не пуста и спит, когда пуста.

 

Вообще вариантов реализации таймеров и их разновидностей много.

 

Это я сказал как оно реализовано в ядре. Для пользователя же, это может быть оформлено, как специальный источник событий. Если пользователь хочет просто получать евент или мессагу в очередь мессаг треда, он попросит EventSource кидать событие в очередь, если захочет написать хук - сделает соотв Listener, и прицепит его к данному EventSource. В первом случае он будет реагировать на event асинхронно, во втором - синхронно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проблемы будут.

Например если список линейный, то если в данный момент(когда прерывания запрещены) поле next у текущего элемента имеет одно значение, то если вы прерывания разрешили, а потом опять запретили...поле next может быть уже совсем другим. а самого элемента this - может уже и не быть в очереди. Кто то его вытащил.

То есть кто-то может вам просто "оборвать" список. Это будет трудноуловимой ошибкой, поскольку получится при коллизии доступа к текущему или следующему элемента списка.

********************

Как будем выкручиваться?

 

Так и я спрашивал о методах работы с "динамическими" очередями (вопр.№3)! Пока приходится изобретать самому. В ОС для Fuji я решил эту проблему для диспетчера - он работает с динамической очередью, в которую обработчики прерываний могут асинхронно добавлять элементы. В ОС над которой я работаю сейчас я эту проблему решил для задачи захвата ресурсов - в очередь могут добавляться элементы и из очереди могут удаляться элементы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если таймеры у вас в системе "жесткие", что обычно бывает в ртоc, то они реализуются так.

На аппаратном таймере сидит процедура, что запускает таймерные хуки(функции определяемые пользователем) по списку "взведенных" таймеров. Такие хуки запускаются синхронно, то есть прямо фактически из прерывания, правда перед запуском хуков прерывания от аппаратного таймера разрешаются.

Хуки не могут пытаться втстать в ожидание, поскольку синхронный код, запускаемый из прерывания не может это делать - система рухнет. Но для особо привязанных ко времени приложений, типа лампочкой попикать или в порт байты кидать - такое - работает хорошо и быстро.

я об этом методе говорил в своем обширном топике - это когда обработчик таймера переходит на т.н. уровень HLL (hardware link layer). Меня не устраивает.

Мягкие таймеры, для задач, когда отклонение на квант работы одного треда не играет роли - например что-то выводить на экранчик периодически юзеру...активируются из системного треда - опросчика таймеров. Он себе крутится пока очередь таймеров не пуста и спит, когда пуста.

Основной вопрос - как управлять приоритетом этого треда? Хотелось бы чтобы его текущий приоритет был равен приоритету запустившего таймер процесса. Конечно можно делать отдельный тред на каждый таймер, но это потребует отдельного контекста, что нежелательно при небольшом объеме ОЗУ.

Возможно я слишком многого хочу, но было бы удобно запускать таймер следующей ф-ей:

timer_start (int ms, void(*callback)(void)), где callback - указатель на ф-ю обратного вызова.

Запускать этот указатель из под прерывания проблем не составляет - у меня есть библиотека и не для ОС (просто вызываешь ф-ю по указателю из обработчика и все).

А вот в треде возникают проблемы о которых я уже писал.

 

Это я сказал как оно реализовано в ядре. Для пользователя же, это может быть оформлено, как специальный источник событий. Если пользователь хочет просто получать евент или мессагу в очередь мессаг  треда, он попросит EventSource кидать событие в очередь, если захочет написать хук - сделает соотв Listener, и прицепит его к данному EventSource. В первом случае он будет реагировать на event асинхронно, во втором - синхронно.

 

про listener можно поподробнее? Это то что я назвал callback?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

***Основной вопрос - как управлять приоритетом этого треда? Хотелось бы чтобы его текущий приоритет был равен приоритету запустившего таймер процесса. ***

 

Зачем? Таймеры - это обьекты чьи срабатывания привязаны ко времени. Чем точнее они привязаны - тем лучше. То есть таймерный тред должен быть более приоритетным, чем все остальные. Мягкие таймеры обычно обслуживают прикладной софт, а жесткие - системный.

 

То есть приоритет таймерного треда должен быть просто выше приоритета тех тредов, что пользуются этими событиями - то есть выше прикладных.

Вообще приоритет расставляется по признаку - что важней.

Никто не мешает запускать несколько тамйрных тредов обслуживающих свое множество таймеров. Один - таймеры прикладные - его приоритет выше махUserPriority, но меньше minSystemPriority. Системные мягкие таймеры обслуживаются тредом, что выше MaxSystemPriority. Ну и так далее.

 

***Конечно можно делать отдельный тред на каждый таймер, но это потребует отдельного контекста, что нежелательно при небольшом объеме ОЗУ.***

Сделать можно, с точки зрения общей теории листенер(ну да это callback оформленный как класс) - будет можно ставить в ожидание, только это весьма избыточно для листенеров вообще.

 

 

***Возможно я слишком многого хочу, но было бы удобно запускать таймер следующей ф-ей:

timer_start (int ms, void(*callback)(void)), где callback - указатель на ф-ю обратного вызова.***

 

Ну оформите так как написали.

 

листенер - это просто класс имеющий виртуальный метод on_event. Создав свой наследник от базового класса, вы переопределяете этот метод, определяя свою функциональность. А у класса EventSource есть метод - add(Listener& fl) и соотв - remove(Listener& fl). Экземпляр листенера вы добавляете к какому-то евентсорсу, технически он заносится в список листенеров данного сорса. при "событии" список листенеров сорса сканируется и у каждого запускается метод - on_event. Так что это колбек, но в терминах ооп. К тому-же каждый листенер может иметь свои переменные в обьекте и работать с ними.

 

Вообще то чем я занимаюсь сейчас...пересказываю сиплюсный текст нашего последннего ядра простыми словами...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем? Таймеры - это обьекты чьи срабатывания привязаны ко времени. Чем точнее они привязаны - тем лучше. То есть таймерный тред должен быть более приоритетным, чем все остальные. Мягкие таймеры обычно обслуживают прикладной софт, а жесткие - системный.

Ну, крыть нечем, обосновали.

Просто тогда неясно как рассчитывать время реакции:

например:

есть N процессов с низким приоритетом, во время работы запускающие таймеры, и 1 процесс с высоким приоритетом, ожидающий события. Это событие возникает и запускает высокоприоритетный процесс на выполнение.

Вопрос: какая будет задержка для худшего случая?

Ответ:

1. В случае, если таймеры наследуют приоритет, то задержка будет равна задержке диспетчера.

2. В случае, если таймеры имеют наивысший пользовательский приоритет, то задержка будет равна времени выполнения всех таймеров плюс какое-то количество запусков диспетчера (у меня - каждые 1 мс). Некрасиво получается.

 

А listener - хорошая вещь. Мне в ОС на С такое приходится делать ссылкой на список аргументов, уничтожаемый при вызове callback. (Ф-я с переменным числом параметров не подходит, потому что они не передаются как надо).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

теоретически вы правы, про таймеры..но

практически - установить N таймеров так что они будут срабатывать прямо все сразу - затруднительно даже специально. Их срабатывание распределено во времени случайно. А метод - on_clock() - обычно очень короткий.

Таймеры в системе о которой я говорю вообще должны работать так, чтобы успеть выполниться до следующего тика аппаратного таймера и не задерживать такт диспетчера до следующего. Поскольку если такое происходит - система станет работать плохо.

То есть в ваших временных интервалах таймеры должны сработать короче чем за 1 мс, а потом переключится тред. То есть задержки быть не должно.

Если же время выполнения on_clock() будет выше чем 1 мс, то это отложит переключение тредов до следующих тактов, что плохо.

Таймеры не регулярное средство программирования, а вспомогательное, просто привязка к физическому времени системы, потому, мое личное мнение, доводить их "до ума" - не стоит.

 

то есть можно сделать так, чтобы таймерный тред менял приоритет - устанавливая его равным максимальному приоритету таймеров в списке...то это вызовет дополнительные расходы на изменение приоритета...впрочем это немного, а вот будет ли реальный от этого эффект - сказать сложно. Если он и будет - то при высокоих уровнях загрузки процессора,..а при таких уровнях говорить о гарантированном времени реакции - вообще уже нельзя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

теоретически вы правы, про таймеры..но

практически - установить N таймеров так что они будут срабатывать прямо все сразу - затруднительно даже специально. Их срабатывание распределено во времени случайно. А метод - on_clock() - обычно очень короткий.

Ну, для soft Real-Time можно рассматривать статистическое распределение срабатывания таймеров, исходя из каких-то предположений. А для Hard Real-Time надо рассматривать наихудший случай (Worst Case Analisys).

 

Таймеры в системе о которой я говорю вообще должны работать так, чтобы успеть выполниться до следующего тика аппаратного таймера и не задерживать такт диспетчера до следующего. Поскольку если такое происходит - система станет работать плохо.

Как я понял, в преиведенном варианте реализации:

Сумма времен исполнения обработчиков <1мс. При этом считается, что запуск и срабатывание таймеров распределены во времени более-менее равномерно. Для большинства задач сгодится. Просто я делаю систему под себя, а в моих задачах есть спорадические события - практически одновременное срабатывание защит, я обрабатываю их таким же способом, но иногда думаю о возможностях оптимизации.

 

Таймеры не регулярное средство программирования, а вспомогательное, просто привязка к физическому времени системы, потому, мое личное мнение, доводить их "до ума" - не стоит.

Ну не знаю, например при организации протокола обмена по сети, например, в соответствии со стандартом OSEK/NMI, к каждому сообщению приходится добавлять таймер. Причем сообщения могут быть и между приложениями. Таймеров набирается много и ,главное, приоритеты у всех различные.

 

то есть можно сделать так, чтобы таймерный тред менял приоритет - устанавливая его равным максимальному приоритету таймеров в списке...то это вызовет дополнительные расходы на изменение приоритета...впрочем это немного, а вот будет ли реальный от этого эффект - сказать сложно. Если он и будет - то при высокоих уровнях загрузки процессора,..а при таких уровнях говорить о гарантированном времени реакции - вообще уже нельзя.

Вы правы. Но проблема не в том, чтобы таймерный тред менял приоритет, а в вытеснении обработчиков.

Пример: сработал таймер с низким приоритетом, запустил обработчик в треде; запустилась задача с приоритетом выше и вытеснила обработчик таймера; сработал таймер с высоким приоритетом и его обработчик ждет окончания совершенно левой задачи, чтобы закончить предыдущий и запуститься.

Т.е. налицо инверсия приоритетов, хотя в данном случае можно использовать протокол наследования приоритетов в самом простом варианте.

 

Кстати, как в Вашей системе решается проблема инверсии приоритетов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В той идеологии, что исповедую я, жесткие таймеры никогда не прерываются тредами. и не могут их вытеснить. Они работают в начале кванта времени системы, остаток же кванта работает какой-то тред.

Мягкие таймеры - по сути просто тред высокого приоритета, и вызываемые из него колбеки - имеют приоритет этого треда, что "крутит" мягкие таймеры. То есть любой тред что выше приортетом, чем тот что крутит таймеры - будет прерывать колбеки этих мягких таймеров.

 

В чем проблема? Я не понимаю, что такое у вас - таймеры высокого приоритета. Зачем придумывать таймерам какие-то иные приоритеты чем приоритет того кода что их вызывает синхронно. Я имею ввиду то, что если низкоприоритетный тред, зачем-то получил доступ к системным мягким таймером(кто вообще дал ему такой доступ? это должно быть блокировано через апи) - то такой хук будет выполняться в высоким приоритетом автоматически.

В хорошем апи системные(то есть суперприоритетные) мягкие таймеры не видны через апи, ими пользуются только системные задачи или треды, те кому предоставлен системный апи.

То есть раскладка по эффективным приоритетам такая.

 

сверху вниз

1. аппаратные прерывания

2. мягкие системные таймеры

3. треды ввода-вывода(те что обслуживают данные берущиеся от прерываний)

4. просто системные треды

5. мягкие таймеры прикладные

6. прикладные треды

7. тред что слипает систему.

 

То есть тут два слоя - системный и прикладной.

Никто не мешает еще подразбить систему на "слои" - это ваше дело. Даже можно вделать в систему механизм генерации такого нового слоя...например существуют среди разрабюотчиков прикладники-полусистемщики и прикладники-типа раздолбай. Вот этим группам можно выделить свой особый слой каждой, тогда вторые не смогут всерьез портить первым жизнь своим разнузданным программированием.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

сверху вниз

1. аппаратные прерывания

2. мягкие системные таймеры

3. треды ввода-вывода(те что обслуживают данные берущиеся от прерываний)

4. просто системные треды

5. мягкие таймеры прикладные

6. прикладные треды

7. тред что слипает систему.

Я уже практически все это реализовал, очень похоже получилось - отр.значение приоритета - системные треды, положительное динамич. значение - прикладные. Но нет предела совершенству ;-)

 

Насчет решения проблемы инверсии приоритетов не могли бы ответить (если не секрет).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я бы не стал на вашем месте концентрироваться на этом вопросе, вы всегда сможете добавить потом нужную функциональность.

Мне кажется это проблема - достаточно академична, и в реальной жизни роли не играет.

Кажется что-то про нее я читал в документации к eCOS. Но в нашей оси ничего подобного мы не делали. У нас была несколько иная архитектура и я прочитал про эти "неприятности" в eCOS- по диагонали.

В любом случае добавить в ядро скрытое изменение приоритетов тредов - проблем не составляет.

 

Когда я говорил о динамических приоритетах, я имел ввиду не этот вопрос конкретно, а возможность треду менять приоритет самостоятельно во время работы. То есть программист может это делать. Но строго говоря - это источник неприятностей связаннных с некорректным стремлением многих программеров, сделать своим тредам слишком выскоий приоритет. Это влияет на другие программы, и часто они начинают работать плохо.

то есть пока я придерживаюсь концепции статических приоритетов, а если и давать возможность программеру менять треду приоритет, тут надо делать еще и какую-то защиту от проблем, что он может породить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я бы не стал на вашем месте концентрироваться на этом вопросе, вы всегда сможете добавить потом нужную функциональность.

"лучше день потерять, а потом за пять минут долететь" - надо мной сроки не висят, есть возможность поэкспериментировать.

У нас была несколько иная архитектура и я прочитал про эти "неприятности" в eCOS- по диагонали.

А что за архитектура такая иная? Можно в общих словах охарактеризовать?

С несравниваемыми приоритетами как у Бабаоглу? (приоритеты задач можно сравнивать только попарно).

Или удалось создать модель реального времени с размножением ресурсов? т.е. без захвата/ожидания?

 

То есть программист может это делать. Но строго говоря - это источник неприятностей связаннных с некорректным стремлением многих программеров, сделать своим тредам слишком выскоий приоритет. Это влияет на другие программы, и часто они начинают работать плохо.

то есть пока я придерживаюсь концепции статических приоритетов, а если и давать возможность программеру менять треду приоритет, тут надо делать еще и какую-то защиту от проблем, что он может породить.

Ну у меня есть динамические приоритеты в смысле повышающиеся с каждым тиком таймера, как у Liu написано. Это может служить некоторой защитой.

Возможно имеет смысл таймер запускать - изменять приоритет на некоторое время?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по моему вы увлекаетесь этими приоритетами. Как показывает практика управлять динамикой задач, просто играя их приортетами, можно только вочень узком дипазоне и потом - это очень неустойчивая система если системе необходим точный тюнинг приоритетов.

Просто софт делится на слои - более важные, менее важные, не важные, совсем никакие и проч. И реально в системе крутятся треды всего-то с 6-7 разными приритетами, вообще их не меняя никогда. И все работает стабильно. ЕСли не работает стабильно то

- что-то написано плохо(обычно как раз то что плохо работает)

- кто-то внаглую отьедает чье-то время и важная задача тормозит.

- система настолько перегружена высокоприоритетными задачами, что никакая новая идеология уже не поможет. Просто надо брать более мощный процессор и больше памяти. либо все написано из рук вон плохо.

Вообщем я бы делал приоритеты статическими, делил систему на слои и имел запас по мощности проца.

И ну их - эти повышения приоритетов по тикам. Кстати чего ради приоритет должен расти от времени? Приоритет это Важность данной задачи по отношению к другим задачам. Важность - понятие статическое. Значит и приоритет должен быть статическим.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По моему мнению, критерий РВ один - предсказуемость. Из этого вытекает мой интерес к приоритетам. Для инверсии приоритетов (основной проблемы для предсказуемости) достаточно трех слоев задач, обращающихся к одному ресурсу. Или в Вашей модели доступ к ресурсам зависит от слоя? Как тогда организуется доступ к памяти (особенно важно для С++)?

И ну их - эти повышения приоритетов по тикам. Кстати чего ради приоритет должен расти от времени? Приоритет это Важность данной задачи по отношению к другим задачам. Важность - понятие статическое. Значит и приоритет должен быть статическим.

Ну как это, ради чего - существует модель анализа Deadline Monotonic, в которой приоритет задачи обратно пропорционален времени до дедлайна. Т.е. указываем время, в течение которого задача должна быть обработана - оно статическое, но если задачу не обрабатывать, то приоритет растет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...