> man operating_systems
Центр информации по операционным системам :: Форумы :: Операционные системы :: Другие ОС
 
<< Предыдущая тема | Следующая тема >>
Реально ли сделать простую ОСь своими руками?
Переход на страницу  1 2 3 ... 9 [10] 11 12 13
Модераторы: Roman I Khimov, Wanderer, Dron
Автор Добавил
prog8
Понедельник 29.03.2010 07:20
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
Посмотрев на устройство разных систем, прихожу к выводу, что моя не так уж и ужасна, как мне иногда кажется.
На самом деле на данный момент у меня имеется два рабочих ядра, я их условно называю os8 и os9 (нормальных названий так и не придумал).
Первое существует в двух версиях - os8-b (Big), которое мы ставим на готовую аппаратуру, и os8-c (on-Chip), которое мы используем для тестирования. "Ончиповая" версия представляет собой минимализированную копию "большой" и предназначена для работы без SDRAM. (Кстати, рабочий процессор у нас - Blackfin, что многое предопределяет.)
Второе ядро показало, как теория может входить в противоречие с практикой. Если первое я делал изначально не имея какого-либо проекта его архитектуры (она сформировалась как-бы сама собой, стихийно), то во втором я первым делом реализовал (очень красиво, на мой взгляд) IPC, целиком построенное на очередях сообщений.
Да, оно работает. Но писать под него драйвера оказалось жутко неудобно, настолько, что я его объявил тупиковой веткой и забросил (хотя оно у нас продолжает использоваться во внутреннем программаторе).

Очередное ядро я решил разработать "правильно" - то есть сначала взять за основу некую прогрессивную концепцию, затем подробнейшим образом продумать его архитектуру, и только потом приступать к кодингу.
Начал я с того, что придумал название - Beeks: Basic Embedded Exo-Kernel System. Сначала первое 'B' подразумевало Blackfin, но поскольку Blackfin - торговая марка фирмы ADI, я не могу использовать ее в названии, так что решил обойтись нейтральным (и гораздо более амбициозным!) Basic.
К настоящему моменту сформировалась такая картина: управление ресурсами полностью "экзоядерное", то есть память (SDRAM), процессорное время и [почти] вся периферия запрашиваются приложениями у ядра и затем используются ими по своему усмотрению, а ядро лишь следит, чтобы не нарушались права собственности;
а вот IPC будет "микроядерным" - все схемы взаимодействия без непосредственного участия ядра, которые я придумал, оказывались либо слишком громоздкими, либо слишком опасными (незащищенными).
Кроме того, ядро обеспечивает единообразный API с периферией; концептуально ничто не мешает вынести и его на прикладной уровень, но устройство Блэкфина делает такой финт слишком уж искусственным и неудобным, да и, честно говоря, ненужным.
Весь ввод-вывод выносится в прикладную библиотеку, которая призвана свести все "стримовые" операции к базовым интерфейсам, предоставляемым ядром.

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

Да, по поводу лицензирования. Я очень хочу сделать свое ядро свободным, но мое начальство пока резко против. Продолжаю ненавязчиво убеждать.
Наверх
Dron
Понедельник 29.03.2010 14:01


ID пользователя #13
Зарегистрирован: Понедельник 05.07.2004 11:16
Местонахождение: Москва
Сообщений: 651
Вообще писать - полезно... пишешь - и у самого возникают новые ответы на вопросы...

У тебя я смотрю как-то очень абстрактно все.
Условия возникновения события ИМХО фрмируются природой события... вото к примеру пользователь ткнул кнопку - событие уже произошло... Дальше надо иметь механизм, чтобы уведомить об этом все заинтересованные приложения.

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

То есть если событие возникает - значит это кому нибудь нужно!

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

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

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

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

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




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

Андрей Валяев
Наверх
Сайт
prog8
Понедельник 29.03.2010 20:36
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
А в микро-экзо-ядре увлекаться конкретикой идеология не позволяет, однако.
И с общесистемными фиксированными буферами нужно проявлять крайнюю сдержанность. В идеале вообще не стоит их иметь, а ограничиться некой "картой ресурсов".
Вот, рассмотрим событие "нажатие кнопки". В моей схеме это есть событие некого интерфейса в неком его канале, то есть, прежде всего должен среагировать соответствующий обработчик прерывания. Допустим, у него есть свой буфер - подчеркну: это не буфер ядра, а буфер обработчика, отделенного от ядра; он запишет туда полученный код и перейдет в состояние "есть данные". А дальше обработка зависит от принятой модели.
1. В ядре есть менеджер событий.
Поскольку интерфейс является контролируемым ресурсом, он имеет свое отображение в ядре.
Смена его состояния (данных нет - данные есть) является событием. Менеджер его улавливает (скорее интерфейс сам должен о нем объявить - так проще), и ищет, не ждет ли некий поток именно этого события; нашел - будит, нет - ну и ладно, интерфейс останется в состоянии "есть данные". Если потом некий поток объявит об ожидании события "есть данные у клавиатурного интерфейса", он не будет усыплен ядром, так как это событие уже наступило.
2. Менеджера событий нет, субъекты сами разбираются с событиями.
У интерфейса есть поле, где хранится id потока, который ждет от него данных. Когда данные появляются, интерфейс обращается к ядру с просьбой разбудить такой-то поток. Ядро лишь должно проверить, разрешено ли данному интерфейсу будить данный поток. Для этого поток, прежде чем заснуть, должен сообщить ядру: "я разрешаю себя будить такому-то интерфейсу". А интерфейсу он сообщает: буди меня при таких-то условиях (в данном случае - как появятся данные). Красиво? Опять же, если потока, ждущего данных, пока нет, интерфейс ничего не сделает; когда поток объявляет интерфейсу о своем желании, его обработчик тут же говорит: "а у меня уже есть данные, просыпайся!"
Вроде, все складно? У меня в os8 подобный механизм реализован. А в os9 реализовано так, что не хочется описанием засорять форум...

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

Если вернуться к буферизации событий, то в моем понимании "пользователь ткнул клавишу 35 раз" - это буферизация не событий, а данных, а событие тут одно: пользователь ткнул.
Да, поток, который ждет данных от интерфейса клавиатуры, это, очевидно, драйвер клавиатуры. От него, в свою очередь могут ждать данных другие потоки; он даже может быть для кого-то "стандартным вводом".


[ Редактирование Понедельник 29.03.2010 20:38 ]
Наверх
Dron
Понедельник 29.03.2010 22:42


ID пользователя #13
Зарегистрирован: Понедельник 05.07.2004 11:16
Местонахождение: Москва
Сообщений: 651
Для меня событие - это сам факт нажатия... а уж последовавшие за этим чтение данных из контроллера всякая другая фигня - следствие...

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

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

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

А эта нить уже транслирует нажатия в поток символов - и передает их другим процессам...

У меня микроядро.

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

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

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

Андрей Валяев
Наверх
Сайт
prog8
Вторник 30.03.2010 07:28
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
У тебя действительно, вряд ли нужно нитям ждать абсолютно одного и того же - это все потому, что мы вкладываем разный смысл в термин "событие". Так подумал... получается, для тебя "событие" = "прерывание". Но ведь и у тебя, наверное, разные нити могут жать разных... не "событий" тогда, скажем, "условий", причем одновременно и от одного объекта, разве нет? Возьмем, например, последовательный порт: одна нить читает из порта и ждет, когда поступят данные, другая нить пишет в порт и ждет, когда данные уйдут. В моей схеме первая нить ждет от драйвера последовательного порта события "есть данные", а другая ждет события "готов", причем от этого же самого драйвера. В это время может появиться третья нить, которой тоже есть что сказать через это же устройство, и она становится в очередь потоков, которые ждут его (устройства) "готовности". Тут еще и приоритеты примешиваются - в какое место очереди становиться, это я как раз уже порешал.

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

Еще есть такая вещь интересная - тайм-ауты. В os8 у меня сделано специальное устройство - "будильник". Любая нить может а) поставить будильник, б) сбросить будильник, в) узнать, сколько еще осталось времени до звонка. Многие операции ввода-вывода должны быть ограничены тайм-аутами - когда что-то долго не срабатывает, мы (то есть, приложения) должны об этом знать. Если вернуться к сокету, то получается, что он может ждать сразу трех различных "событий" (в человеческом значении слова) - 1) пакета из сети, объект "сеть"; 2) истечения тайм-аута, объект "будильник"; 3) обращения от приложений, причем здесь объект не может быть конкретизирован. Проснувшись, он первым делом выясняет, что именно его разбудило, т.к. реагировать нужно по-разному.

-----------------
Меня тут гложут сомнения - а не перестарался ли я со своими "разрешениями будить"? С одной стороны, для защиты это вроде бы важно - нельзя всем разрешать будить всех, а то появится этакое "хулиганистое" приложение, и как пойдет всех подряд будить... Ничем хорошим это не кончится. С другой стороны, а как реализовать? Ладно, если разрешаю будить кому-то одному, но этого точно мало. Держать массив "доверенных" субъектов? Неудобно. Думаю вот теперь.
Наверх
Dron
Вторник 30.03.2010 10:35


ID пользователя #13
Зарегистрирован: Понедельник 05.07.2004 11:16
Местонахождение: Москва
Сообщений: 651
prog8 написал(а) ...
У тебя действительно, вряд ли нужно нитям ждать абсолютно одного и того же - это все потому, что мы вкладываем разный смысл в термин "событие". Так подумал... получается, для тебя "событие" = "прерывание".


Не, не прерывание... Событие - это нечно, происходящее с ресурсом...
Прерывания - это сугубо ядерный процесс...

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


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

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


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

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


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

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

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


Вот это мне и не нравится. мне хочется чтобы объект заранее знал что его будит, и ему не придется выяснять это дополнительно...

Взять те же сокеты... есть приход данных от устройств... есть ограничения операций по времени.. Но всем этим заправляет один драйвер (TCP к примеру), и он вполне может иметь один поток для приема пакетов от драйвера IP, один поток для сортировки пакетов по соединениям, другой поток по отслеживанию таймаутов (который будет грохать соединения).
Те приложения, которые приходят за данными в моей системе - они автоматически создают новую нить (у меня так вызовы организованы) - то есть приложения забирают данные каждое в своем потоке. Получается что каждый поток делает одно действие - достаточно близкое к элементарному. Необходимости в множественном ожидании не наблюдаю.

prog8 написал(а) ...
а то появится этакое "хулиганистое" приложение, и как пойдет всех подряд будить... Ничем хорошим это не кончится. С другой стороны, а как реализовать? Ладно, если разрешаю будить кому-то одному, но этого точно мало. Держать массив "доверенных" субъектов? Неудобно. Думаю вот теперь.


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

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

Андрей Валяев
Наверх
Сайт
prog8
Вторник 30.03.2010 12:07
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
Dron написал(а) ...
ожидать готовности порта здесь уже не нужно.
...Но нужно ожидать готовности драйвера? Или просто у него есть очередь сообщений, приложения шлют драйверу сообщения и ждут ответа, а драйвер разгребает их в меру сил в порядке очереди? (Это у меня в os9 так, кстати.)

Dron написал(а) ...
Те приложения, которые приходят за данными в моей системе - они автоматически создают новую нить (у меня так вызовы организованы) - то есть приложения забирают данные каждое в своем потоке.
Да, совсем другая идеология. Я избегаю излишнего создания нитей, мне кажется, это слишком увеличивает накладные расходы системы, ведь нужно: 1) создать нить, зарегистрировать ее в ядре; 2) выделить ей ресурсы; 3) передать ей какие-то дескрипторы; 4) переключаться из/в ее контекст(а), пока она работает; 5) синхронизировать с ней другие нити (если надо); 6) получать от нее данные, передавать ей данные; 7) наконец, убить нить - разрегистрировать, забрать ресурсы.

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

Dron написал(а) ...
У меня все в системе на способностях строится... если ты можешь что-то сделать с объектом - тебе повезло... по умолчанию - не можешь.
Это понятно. Но кто определяет, можешь ты, или нет? Наверно, ядро, кому еще? А как? В этом и вопрос. Ну, теоретики скажут: у каждого защищаемого ядром объекта должен быть свой security descriptor, который четко определяет, кому и что можно делать с данным объектом. Хорошо, тогда возникает куча вопросов: где ядро держит этот дескриптор? как он устроен? как ядро отслеживает характер доступа к объекту? как быстро ядро может обрабатывать дескриптор (подразумевая, а не будет ли такая система слишком "тормознутой")? сколько памяти нужно отвести на дескрипторы (подразумевая, а хватит ли нам ядерной памяти)?
На меня накложены жесткие ограничения по расходу памяти и процессорного времени, и это очень сильно влияет на архитектуру системы. Так, ядро я обязан упихать в 32 кб кода и 32 кб динамических данных - больше просто НЕТ (вернее, может не быть - есть у нас такие борды). Так что особо не разгуляешься. Вот и думаю сейчас над устройством секьюрити дескрипторов.
Наверх
prog8
Вторник 30.03.2010 12:14
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
Да, еще, извини за нескромный вопрос: а ты в своей системе поддержку сети сделал? Если да, то было бы ОЧЕНЬ интересно почитать, как именно, с расписыванием по всем объектам, нитям, и т.п... если не секрет, конечно. Мне не очень нравится, как я все реализовал в os8, и когда я покончу с ядром (это примерно через месяц), надо будет браться за сеть, а я еще и не знаю, как ее лучше сделать.
Наверх
prog8
Вторник 30.03.2010 12:25
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
Ладно, сразу уж, до кучи: а многоядерные процессоры твое ядро поддерживает? Это еще интереснее. Мы уже заказали партию 561-х блэкфинов, а они, гады, двухъядерные... В этом направлении у меня вообще никаких идей пока.
Наверх
prog8
Вторник 30.03.2010 14:29
ID пользователя #1343
Зарегистрирован: Пятница 26.03.2010 07:27
Сообщений: 27
Перечитал сейчас свой "журнал размышлений" - оказалось, твои идеи мне не чужды. Цитирую:
"Ожидать какого-либо события может только поток, поэтому логично было бы добавить в его дескриптор (ссылкой или непосредственно) структуру «ожидание события». Сложность в том, что поток может ожидать сразу нескольких событий. Если можно придумать такую структуру, в которой бы отразились сразу все ожидания – это было бы хорошо; иначе придется делать массив ожиданий, что хотя и обрабатываться будет более громоздко, но с другой стороны дает гораздо большую гибкость в использовании. Кстати, в юниксах есть сисвызов select(), который предназначен как раз для этих целей: там задаются три массива файловых идентификаторов и тайм-аут; можно сделать так же, но мне этот подход почему-то никогда не нравился, казался очень неестественным.
Если к каждому потоку привязать некий массив ожиданий, то есть массив структур, в которых будет однозначно описано, чего именно ждет поток, то возникает проблема обработки этих массивов. Может так получиться что несколько потоков ждут однотипных событий от одного и того же объекта, и в этом случае они должны образовать очередь, потому что одновременные команды все равно невозможны – как только объект получит одну команду, он тут же перестанет быть «готов», и будет не готов, пока не выполнит команду, так что второму потоку снова нужно будет впадать в ожидание. Таким образом, мы вернулись к идее очередей захвата.
Для простоты можно положить, что поток не может ожидать события более, чем от одного объекта, и дальше потом как-то с этим крутиться. В os8 дела обстоят именно так, и там возникает проблема с сокетами – каждый сокет с одной стороны ждет пакета из сети, а с другой стороны в то же самое время ждет команды от потока-клиента. Даже если перевести сокеты в специальную файловую систему, все равно придется либо ожидать событий от двух объектов (от сети и от пайпа), либо делить поток на два, чтобы один ждал события от сети, а другой от пайпа. Наконец, при нескольких сетевых интерфейсах также было бы разумно ждать пакета из всех интерфейсов одновременно. Но можно вывернуться и сделать состояние «абстрактного ожидания», то есть быть готовым принять команду от кого угодно, а драйверы сетевых устройств сами отдавали бы принятые пакеты.
Такой подход – с одиночным ожиданием – с одной стороны сильно урезает возможности приложений, но с другой стороны усиливает контроль, упрощает взаймодействие, и серьезно уменьшает вероятность ошибок, предотвращая конфликты доступа."
Наверх
Переход на страницу  1 2 3 ... 9 [10] 11 12 13  

Перейти:     Наверх

Транслировать сообщения этой темы: rss 0.92 Транслировать сообщения этой темы: rss 2.0 Транслировать сообщения этой темы: RDF
Powered by e107 Forum System

© OSRC.info, 2004-2010.
Авторские права на любые материалы, авторы которых явно указаны, принадлежат их авторам. По вопросам публикации таких материалов обращайтесь к авторам.
Авторские права на любые другие материалы принадлежат OSRC.info.
Сайт является помещением библиотеки. Копирование, сохранение на жестком диске или иной способ сохранения произведений осуществляются пользователями на свой риск.
При использовании материалов сайта ссылка на OSRC.info обязательна.