Pull to refresh

Comments 8

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

. Ещё есть RunToComplition РТОС, з с вытеснение. Там задачи без собственного стека,, просто функции ззапускающиеся на общем стеке и только по источнику события.

Т. е пришло событие, планировщик пнули, он запустил задачу, если надо вытеснил низкоприоритетну задачу - все. Если его пинают, значит обязательно есть задача для запуска.

Прямо затраты по ресрусам копеечные + быстрое переключение.

Когда на однопоточных (одноядерных) системах начинают обзывать задачи потоками и говорить про параллельную работу, при чем опытные разработчики, немного корежит…

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

Скажем, в большинстве вариантов OS/360 (а это вторая половина 1960-х), кроме самых примитивных, были и процессы, и потоки, только то, что в винде включается в термин "процесс", размазывалось между разделом памяти и задачей пункта задания, а "потоками" были эта самая задача пункта задания (головной поток) и порождаемые ей подзадачи.


В RSX-11M -- "бабке" Винды (середина 1970-х) -- были лишь "процессопотоки", называемые, внезапно, задачами, и даже выполняемые файлы ("экзешники") имели расширение .TSK. И да, они выполнялись параллельно в режиме вытесняющей многозадачности.

В общем, простите, задачи -- исторически это и есть параллельная работа.

Для атомарного доступа, вместо отключения прерываний, в процессорных ядрах ARM Cortex M есть специализированное решение – инструкции эксклюзивного доступа LDREX/STREX. Этот механизм защищает конкретный адрес памяти от несанкционированного доступа – доступ из прерывания.

С этим тоже есть проблемы, причём, по меньшей мере, две:

  • есть ядра Cortex-M0 (архитектура ARMv6-M), у которых этих команд нет вообще;

  • есть двухъядерные микроконтроллеры STM32H745 и иже с ним, где у обоих ядер (Cortex-M7 и Cortex-M4) эти команды есть, но вот глобальный монитор монопольного доступа разработчик МК почему-то не реализовал, из-за чего эта парочка команд может использоваться весьма ограниченно -- только если она должна обеспечить атомарность при доступе строго для одного ядра; если к чему-то нужно атомарно обращаться кодом, выполняющимся на разных ядрах, -- всё, приходится делать что-то другое, например, использовать аппаратные семафоры (блок HSEM), неализованные на этом семействе МК.

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

Не будет оно проигнорировано -- оно будет сохранено в ожидании обработки, и его обработчик будет вызван, как только станет возможным. Точно то же самое имеет место и на ARMах с NVICом: если низкоприоритетное прерывание запрашивается в момент, когда выполняется обработчик высокоприоритетного прерывания, низкоприоритетное запоминается и ждёт.

Эта статья не урок истории. 1960... Еще бы первый компьютер упомянули. Это прекрасно, что вы знаете историю, но речь идет про сегодня.

А про игнорирование прерывания говорилось в контексте вложенности...

Как будто в 90е вернулся! Мы именно так под DOS и писали программный код! Единственное прерываний там не было, а сейчас я так-же, как в статье, для МК код пишу. Самое понятное (возможно для меня привычное) и отчасти многозадачное решение получается.

Ждем следующую часть.

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

Работал в давние времена в компании, занимавшейся разработкой АТС. Там был интересный подход в реализации вытесняющей многозадачности. Был обычный луп в мэйне с фоновыми не критичными тасками. И было внешнее прерывание c периодом 2мс, синхронизированное со сверхциклом Е1. Прерывание это вложенное, т.е. если во время выполнения процедуры прерывания произошло ещё одно прерывание, то контекст пушился в стек и вызывалась функция данного уровня приоритета со своими FSM (был счётчик вложенности прерываний и массив указателей на функцию). После выхода из функции контекст пОпался и предыдущая функция продолжала выполняться и т.д.

Я так понимаю речь идет про старые RISC-V, где вложенные прерывания нужно было обработать ручками. В современных ядрах RISC-V пытаются это дело автоматизировать, как в ARM CM, но как там успехи не знаю...

Главная задача MMU заключается в предоставлении и обеспечении безопасности

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

MMU и виртуальность прежде всего защищают память от фрагментации. Без MMU стараются не использовать динамическое выделение памяти, потому что фрагментацию при многозадачности очень сложно предсказать.

Sign up to leave a comment.

Articles