OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Пятница, 29 Март, 2024 02:07

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
СообщениеДобавлено: Среда, 04 Октябрь, 2017 21:21 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
В другой ветке опять упомянута проблема избегания динамического выделения памяти.

Для ответственных применений динамика может быть структурирована по стадиям рантайма.

На позапрошлый День Оберона Дмитрий Дагаев делился опытом использования ОС A2\Active Oberon в атомной отрасли. Выделение всей структуры динам. объектов делается при запуске, после чего NEW и GC просто выключаются.

Чуть шире рассуждая.

Стадия инициализации и конфигурирования может спокойно использовать динамику.
Рабочая стадия системы управления может ничего не выделять.

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

И отдельно, конечно, идёт выделение памяти под потоки обрабатываемых данных, в случае систем управления, имеющих такие потоки данных в реальном времени.
Выделение памяти скрывается под капотом абстрактного типа данных (страничные буферы и т.п.).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 04 Октябрь, 2017 22:10 

Зарегистрирован: Вторник, 01 Март, 2011 09:34
Сообщения: 583
Откуда: Москва
Я бы рекомендовал определить резервы по числу сигналов (напр., 100 аналоговых, 200 дискретных, 100 32-битных телеграмм), а при стадии конфигурирования вводить сигналы из резерва в работу. Операции NEW не потребуется.

Если не получается, то аллокировать при инициализации, затем старт, рабочая стадия, при отказе - перезагрузка.
У меня после аллокирования шел старт
Код:
BEGIN {ACTIVE,SAFE}
    DoStart();
    Цикл Idle с Await
END

Если шел сбой (или овертайм по счетчику времени), то увеличивался счетчик ошибок и снова рестарт, но уже без аллокирования.
Если есть требования рестарта "задачи" от сбоев, то нужно как-то защититься от сбоя уже аллокированной памяти. Я эти деревья дублировал, запоминал md5 и сравнивал отдельной диагностической задачей.

Хотя можно придумать другие варианты с памятью.
- Хранить дерево в статическом массиве максимальной длины;
- Попробовать поковырять модуль Heaps в A2, чтобы для каждой задачи выделить свою фиксированную область памяти кучи (я это не делал, так навскидку). И при перезагрузке будет выделяться память из своей кучи.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 04 Октябрь, 2017 22:19 

Зарегистрирован: Вторник, 01 Март, 2011 09:34
Сообщения: 583
Откуда: Москва
В контроллерах на МЭКовских языках сажают функциональные блоки на определенные адреса. Также и Ваших задачах можно: взять 4 задачи, разбить память на 4 части, выделить в каждой задаче статический буфер, и выделять память на только этом буфере своим менеждером кучи. Но это то же самое, другими словами.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 04 Октябрь, 2017 23:40 
Аватара пользователя

Зарегистрирован: Воскресенье, 12 Апрель, 2015 18:12
Сообщения: 1134
Откуда: СССР v2.0 rc 1
В замкнутой системе зачем динамизм? Нечему и негде там появиться. Вместо выделения памяти, проще использовать массив типа объектов, где один из признаков -- блок занят\свободен. Илья также свои задачи решает, это самый простой путь.
Это вполне себе решение для робомобиля.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Октябрь, 2017 12:53 

Зарегистрирован: Пятница, 13 Март, 2009 16:36
Сообщения: 987
Откуда: Казань
В некоторых случаях можно обойтись выделением динамической памяти при инициализации, а в некоторых случаях нельзя.
Например, если мы проектируем тектовый редактор с поддержкой undo, то для поддержки undo необходимо выделять память. При этом мы не можем точно знать, сколько именно будет редактирований (может быть за редактор сядет Лев Толстой и начнет писать "Войну и Мир" и при этом не будет сохранять файл до того, как роман будет завершен :) )


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Октябрь, 2017 14:15 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
Илья Ермаков писал(а):
Стадия инициализации и конфигурирования может спокойно использовать динамику.
Рабочая стадия системы управления может ничего не выделять.

В Активном Обероне/А2, например, может быть активность реального времени. Из этой активности можно вызывать только процедуры/методы реального времени (они помечены как REALTIME). В них нельзя вызвать NEW, компилятор стукнет по рукам. Но в инициализаторах выделить память можно.
То есть здесь явное разделение - инициализация, с возможным выделением динамической памяти, и рабочая стадия, где выделение памяти запрещено. Ну и РВ-задачи вытесняют сборщик.
Проблема в том, что задачи реального времени не разделяются по приоритетам, то есть REALTIME это один самый высокий приоритет, а хотелось бы чтобы было хотя-бы 3 - низкий, нормальный, высокий. Тогда можно строить свои РВ-решения на этой базе.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Октябрь, 2017 14:16 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
Rifat писал(а):
В некоторых случаях можно обойтись выделением динамической памяти при инициализации, а в некоторых случаях нельзя.
Например, если мы проектируем тектовый редактор с поддержкой undo, то для поддержки undo необходимо выделять память. При этом мы не можем точно знать, сколько именно будет редактирований (может быть за редактор сядет Лев Толстой и начнет писать "Войну и Мир" и при этом не будет сохранять файл до того, как роман будет завершен :) )
Это же не критическая/РВ задача


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Октябрь, 2017 16:47 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
prospero78 писал(а):
В замкнутой системе зачем динамизм? Нечему и негде там появиться. Вместо выделения памяти, проще использовать массив типа объектов, где один из признаков -- блок занят\свободен. Илья также свои задачи решает, это самый простой путь.
Это вполне себе решение для робомобиля.


(Статическая распиловка, кстати, и в ГРАФИТ-ФЛОКСЕ у НПЦ АП, в этом плане вполне тот же подход (попилили, при этом попиловка памяти в единой коллективно доступной БД, и над этим крутятся алгоритмы)).

Использование объектов и POINTER TO имеет архитектурные плюсы (особенно в системах со статическим составом, но динамической структурой, графы типа маршрутности и т.п.). Гораздо удобнее, чтобы параметром какому-нибудь алгоритму уходил указатель на объект, а не пара "массив, индекс" (а у объекта есть метаинформация о том, кто он, кто его родительский узел, кто следующий в цепи и т.п.)
С таким графом объектов удобно работать, совсем другой уровень программирования (до сих пор непонятный и далёкий для некоторых инженеров-электронщиков, которым чуждо понятие "напиши один раз - используй несколько", обобщение и т.п.).
Но аллокация всего этого хозяйства для объекта статической структуры может выполняться один раз при старте.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Октябрь, 2017 20:24 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
Илья Ермаков писал(а):
В другой ветке опять упомянута проблема избегания динамического выделения памяти.
Для ответственных применений динамика может быть структурирована по стадиям рантайма...

Динамическое управление памятью возможно, а иногда, фактически, неизбежно, как здесь, например:
Scalable Task Parallelism for NUMA: A Uniform Abstraction for Coordinated Scheduling and Memory Management

Однако в оригинале (если правильно понимаю контекст) речь была не столь о динамическом выделении памяти как таковом, а скорее о динамическом изменении структуры процессов в целом -- запуск/останов задач, создание каких-то объектов и т.п., и, прежде всего, о последующем влиянии такой динамики на возможность контроля "качества" -- проверка или верификация программ.

В дополнение к материалам в этой теме приложил пару вводных статеек (из публ. источников) -- в целом об Esterel-платформе и некая модификация SWITCH-технологии для использования Esterel-фишек для верификации программ:
Вложение:
Синхронное программирование.pdf [244.41 КБ]
Скачиваний: 278

Вложение:

Правда, Шалыто или его студенты/аспиранты некорректно понимают "сильное/слабое вытеснение" -- так они обзывают разницу между операторами abort и suspend. На самом деле suspend -- именно приостановка исполнения процесса, а "сильное вытеснение" -- прерывание работы процессов сразу же при возникновении определенного условия, "слабое" -- после итерации очередной обработки сигналов. Здесь было пару слов:
viewtopic.php?f=152&t=6049#p101207
или детальнее:
Preemption in Concurrent Systems

Проблематика динамики касается не только сферы встроенки, а в целом "программирования общего назначения". Такие языки как Lustre/Lucid Synchrone/Signal смело можем объединить и понимать их как единый язык, плюс добавить Esterel-примитивы как в проекте Ceu (подробности были в той смежной теме). Пусть у нас возникает некое подмножество ML.

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

Сопутствующая потоковая модель имеет иную особенность. Вот здесь хорошо отражена суть "clock"-ов с картинками -- понимание такта автомата и учёт наличия/отсутствия сигнала:
Enhancing the Compilation of Synchronous Dataflow Programs with a Combined Numerical-Boolean Abstraction

Выше пример альтернативной технологии проверок (в базовых средствах иное исчисление). Или вот в целом проблематика:
Liquid Clocks - Refinement Types for Time-Dependent Stream Functions

Т.е., как только написали программу (или даже отдельную функцию), как бы обычным способом на программистском языке (ну или чего-то где-то дорисовали на диаграммках), и её проглотил компилятор -- уже есть гарантия (и ряд оптимизаций) достижимости конечной точки, т.е. реакция системы будет всегда определена на любой возможный вход. Таковы базовые средства "качества". Ессно, насколько возможный выход соответствует предметной прикладной логике управления и не было ли чего плохого по ходу дела (опять же с точки зрения конкретной предметки) -- отдельные задачи тестирования и проверок по потребности (конечно, имеются и соответствующие инструменты).
Причём потоковые асинхронные (истинно параллельные) процессы также автоматом проверяются. О них подробнее здесь:
Programming Parallelism with Futures in Lustre

Теперь пусть наш условный язык программирования расширяется до полных возможностей ML -- в данном случае подразумевается возможность динамически создавать/удалять процессы и различные объекты. Вот пример возможной техники верификации в подобных случаях:
Verifying Event-Driven Programs using Ramified Frame Properties

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

Как правило, динамически создаваемые процессы (в т.ч. и параллельные или асинхронные) вынуждены общаться через каналы ввода/вывода (а не через аргументы процедур/функций, хотя в потоковой модели выше имеется возможность создавать несколько экземпляров процесса, но структура процессов всё-таки известна заранее, и техника проверок соответствующая). Каналы связи необходимы и для распределенных процессов. В таких случаях методика верификации обычно в стиле SPIN-а. Однако учёт динамики изменений -- ещё та задача (тут истинный "мегавзрыв состояний"). У Microsoft есть неплохие наработки в таких случаях в рамках языка "P Language":
https://www.infoq.com/news/2016/10/micr ... pensourced
https://github.com/p-org/P

Подробнее:
P: Safe asynchronous event-driven programming
Systematic testing of asynchronous reactive systems

В дополнение о сложности проверок, если необходимо отслеживать всякие нюансы. Вот, к примеру, учёт особенности "вытесняющей" многозадачности -- обычных тред-ов в обычных операционках с переключением контекста со стороны ОС:
Iterative Context Bounding for Systematic Testing of Multithreaded Programs

Если необходимо учитывать указатели:
Proving Termination and Memory Safety for Programs with Pointer Arithmetic

Выше под "termination" понимается прежде всего ограниченность "блуждания" по массивам через указатели и т.п. О завершимости в контексте циклов/рекурсии -- пример ниже, где автоматом выявляются зависимости, причём оценка рекурсии выполняется во взаимодействии с прочими предикатами:
Better termination proving through cooperation

Итого, учёт динамики для "качества" очень таки возможен, но очень и очень непросто, однако.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 05 Октябрь, 2017 20:42 

Зарегистрирован: Понедельник, 25 Июнь, 2012 17:26
Сообщения: 473
Дополню, раз уж тут такая пьянка завелась. В смежной теме была хорошая статейка насчёт проблематики проверок в целом:
Specification and Validation of Embedded Systems: A Case Study of a Fault-Tolerant Data Acquisition System with Lustre Programming environment

, где подчёркивается такое свойство верификации как “locally” в отношение всей системы:
Цитата:
Ideally, the formal verification of such a program should
consist of comparing it with a global, abstract specification.
As it is often the case with real case-studies, this specification
is not available. The problem even more serious, here, since
the abstract specification of such a fault-tolerant system
should probably involve probabilistic properties, which are
stated nowhere, and which could not be handled by usual
verification tools.
So, we don’t know “what to verify” on the complete
program. However, there are two common cases where
verification tools can be applied “locally”:
* When there are two ways of writing a node, one can write
both and try to show that they are equivalent. If they are
not, a bug is detected, at least, in one of them. If they
are, this increases the confidence one can have in any of
them. We will illustrate this situation on two versions
of the node "values_nok", which detects cross-channel
faults.
* When some consistency properties are clearly expressed
in the requirements: for instance, we will try to prove
that at most two channels can become “reset-inhibited”

Т.е. базовый язык как Lustre даёт гарантии завершимости, но как только начинаются "танцы с бубнами" по конкретной предметке -- неизбежно лишь частично по потребности (и обычно после первичного тестирования) начинаются всякие верификации отдельными кусками (причём “locally” не зависит от инструментов или языков -- общий результат сути верификации как таковой в целом).
Однако фишка "синхронной школы" в этом:
Илья Ермаков писал(а):
Собственно, мы тут уже обсуждали, что всё идёт к тому, что в центре разработки - системная модель (при этом единая для разработчиков СУ и для системных инженеров),
а от неё уже идёт проектирование СУ и порождение кода (автоматическое или частично автоматическое).
...
Вообще, технологии, основанные на выделении состояний - это хорошо.
Но с примитивными КА не всё гладко. Как только начинаешь разделять состояния МОДЕЛИ управляемой системы и внутренние состояния самой управляющей системы...

Т.е. вопрос развития этих подходов стоит.

Вы же приводите как раз уже нечто другое, чем Эстерелевские диаграммы состояний.
Полноценные языки программирования.

Так вот, здесь именно что "язык программирования" и "модель системы" -- в одном флаконе. Была попытка уточнить принцип взаимодействия автоматов:
viewtopic.php?f=152&t=6049#p101208
, но сложно кратко описать суть. Попробую чуть подробней.

Итак, ранее в той теме были ссылки, к примеру, на провал "состояний типов" в Rust-e:
http://pcwalton.github.io/blog/2012/12/ ... e-is-dead/

А собирались там реализовать технику как в Vault -- экспериментальное расширение С от MS:
https://www.microsoft.com/en-us/researc ... pldi01.pdf

В данном случае подразумевается поддержка "протокола ресурсов" -- отслеживание порядка операций над объектом (а также "время жизни" -- регионы памяти), представляя последний как виртуальный автомат -- см. рисунок:
Вложение:
protocol.png
protocol.png [ 51.55 КБ | Просмотров: 7207 ]

В общем случае требуются двусторонние и более протоколы взаимодействия. В программистской интерпретации -- "сессионные типы":
http://simonjf.com/2016/05/28/session-t ... tions.html

Тема тяжёлая. Однако, "французы" в 80-х не страдали отдельными языками разработки для указания взаимодействия, как, напр., Scribble (выше по ссылке). Всё в рамках "обычного" -- пишется код работы процессов, проверяется и т.д. Затем по потребности при генерации кода на С или спецификаций для железа процессы могут быть "разрезаны" -- разнесены по узлам, программам и т.д., в т.ч. формируется подсистема сетевого взаимодействия и т.п. по потребности.

Вот в этой статейке про "объекты-автоматы":
https://pdfs.semanticscholar.org/f570/9 ... 83acca.pdf

наглядный пример автоматического определения протокола на основе кода программ (спецификации, конечно, могут быть указаны и вручную).
Подобную технику возможно обобщить через систему типизации, с учётом "разрыва" типа. Можно воспользоваться примером реализации сессионных типов для Java:
Type-Safe Eventful Sessions in Java

, где на борту имеются механизмы runtime-нарезки сессий -- т.е. "разрыва" типа-сессии (см. оператор typecase и пр.). В данном случае пример реализации вэб-сервера, где ядро программы как подсистема ввода/вывода вокруг сокетов, обслуживающее много клиентов. При возникновении событий (коннекты, получение данных) -- виртуально "воссоединяются" серверный и клиентские процессы -- возобновляется обработка данных по протоколу.

По таким мотивам. Определим некий протокол взаимодействия, псевдокод:
Код:
procedure Protocol(A, B: side) = (s: string);
{
    START:> var i at A: int = proc1();
    ST1:>   var f at B: float = proc2(i);
    ST2:>   s at A = proc3(f);
}

Пусть это будет некая реальная программка, проверяемая по ранее указанным техникам. Здесь "side" -- специальный тип, символизирующий сторону контракта -- как, напр., в том же Scribble. Про оператор "at" здесь подробнее:
http://www.di.ens.fr/~guatto/papers/lctes12.pdf

, т.е. это указание "региона" как в Rust (но техника в целом значительно проще), однако в данном случае понимается по-особому (виртуально) из-за использования типа side. Запись вида "START:>" -- обычные label в ML-стиле (главное идентифицировать процессы, в принципе достаточно переменных-"сигналов"). Код понимается примерно так: выполняется proc1 условно на стороне A, затем proc2 (использующий результат от poc1) на стороне B и т.д.

Теперь можем определить некий процесс "воссоединения", пусть на стороне вэб-сервера -- сторона А, т.е. где-то на сервере при сокет-событиях будет выполняться "продолжение" сессии:
Код:
procedure SomeProc(h: handle, o: object; var ts: typestate[h, Protocol(_,*)]);
{
    match ts with
        | START =>
            var i: int = o.get_data;
            write(h, i);

        | ST1 =>
            var f = read[float](h);
            ST2(f);

        | ST2(f: float) =>
            o.set_data(f);
    end;
}

Здесь аргументы: "h: handle" -- дескриптор для ввода/вывода (некий сокет), "o: object" -- какой-то объект на сервере, исполняющий "o.get_data" -- это есть proc1 по протоколу, "o.set_data" -- proc3.

Аргумент "var ts: typestate[h, Protocol(_,*)]" -- специального типа для отслеживания состояния сессии, параметризуется каналом связи и протоколом (символы "_" и "*" -- согласно обычному pattern matching -- некое значение и его отсутствие соответственно -- так указали, что задействована сторона A). Для аргумента ts компилятор отслеживает операции -- переходы на условные состояния сессии, и корректирует его значение -- подробнее см. "Sessions in Java" выше.
Предполагается, что компилятор понимает семантику операций вида read, write, flush и т.п. для ввода/вывода, соответственно и контролирует порядок их применения. Полагаю, смысл кода очевиден без уточнения. Оператор match в данном случае напоминает "автоматы", как здесь (про "automaton" или "mode"):
viewtopic.php?f=152&t=6049#p101207

В примере, прежде всего, контролируется семантика сетевого взаимодействия или ввода/вывода. Контроль операций для "o: object" -- "get_data/set_data" -- через свой протокол типа. Или же расширить typestate выше.
Переменные типа typestate -- неизбежны в любом случае, как бы вручную не реализовывались бы "сессии". Однако этот флаг пусть лучше контролирует компилятор.
Такая техника универсальна. К примеру, если определить кортеж вида (h: handle; ts: typestate), то компилятор всегда сможет отслеживать корректность, даже если переменные "улетают" из области видимости, к примеру, вносятся/извлекаются в контейнеры данных.

В общем, примерна такова политика для языка программирования. Причём годится она для реализации как и для жёсткого realtime, так и для попсового текстового редактора. Проверки по потребности, где-то рядом сбоку, с учётом "разрыва" типа.

В целом задачи верификации, конечно же, шире. Здесь на форуме когда-то был представлен ГрафКонт -- специфичные отношения между процессами. Возможно допустимо понимать их как дополнительные ограничения в протоколах, в т.ч. и для синтеза систем (или решения задач планировщика).
Вот ещё пример отношений между процессами (с картинками):
Contracts and Behavioral Patterns for SoS: The EU IP DANSE approach

Или же подобные отношения выражаются через "сигналы" у тех же "французов" (для периодических процессов с разными частотами):
A Real-Time Architecture Design Language for Multi-Rate Embedded Control Systems


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB