четверг, 20 марта 2008 г.

Что-то с памятью моей стало...

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

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

Но неладно что-то в датском королевстве...

Попытавшись поставить 2 мегабайта для bochs я услышал от GRUB следущее:

GNU GRUB version 0.96 (639K lower / 4193279K upper memory)

Хех, очень забавно... То же самое я увидел запустив qemu... И что самое интересное, что то же самое GRUB докладывает моему ядру.

Попробуем поднять планку до 4 мег.

GNU GRUB version 0.96 (639K lower / 1984K upper memory)

bochs и qemu вновь единодушны, но где еще один мегабайт??? Ведь по логике вещей должно быть 3М upper...

8M: GNU GRUB version 0.96 (639K lower / 6080K upper memory)
16M: GNU GRUB version 0.96 (639K lower / 14272K upper memory)

Нет, надо с этим что-то делать...

PS: Одно место обнаружилось в bochs bios, он от размера памяти отнимает ACPI_DATA_SIZE, но это не может послужить причиной пропажи целого мегабайта, ACPI_DATA_SIZE имеет значение 64к.

PPS: Эх, чуть чуть недотестировал...

17M: GNU GRUB version 0.96 (639K lower / 16320K upper memory)!

Ошибка скрывалась в Биосе bochs в функции 0xe820, int 0x15. Если памяти больше 16 мегабайт, то анализируется количество 64-х килобайтных блоков после 16 мегабайт, 16 мегабайт прибавляем. А если памяти ровно или меньше 16 мегабайт, то анализируется количество килобайтных блоков после мегабайта... А вот мегабайт прибавить забыли.

QEMU использует биос из комплекта bochs, поэтому проблема присутствует и там.

четверг, 13 марта 2008 г.

Извращенное usability...

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

Но начну издалека...

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

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

Недавно в руки ко мне попал ноутбук, ну кое что настроить там нужно, не важно, с Windows Vista... Всем, конечно, известна моя нелюбовь к продуктам Майкрософт, но я стараюсь быть корректным. В какой то момент, глядя на качающийся из стороны в сторону прогрессбар, я подумал: "Вероятно первое появление прогрессбаров было весьма революционным - как удобно, сразу видно сколько осталось до конца". Потом, видимо, кто-то решил добавить немного динамики, или просто степень завершения работы была неизвестна и придумали прогрессбар, который никогда не кончается. В данном случае он качается из стороны в сторону, бывают варианты что он, дойдя до края, начинается сначала (вот облом..), но результат один.



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

вторник, 11 марта 2008 г.

Есть ли жизнь без MMU...

Последнее время, с тех пор как занялся с LPC2468, много думаю на эту тему.

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

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

Код приложений должен быть безопасен. Безопасности можно достичь использованием типобезопасного языка. Cразу вспоминаются системы с единой памятью, типа Bluebottle, Singularity... Которые собственно и создаются без учета MMU как такового. При демократии (использовании любых языков) с безопасностью дела обстоят гораздо сложнее. Всмысле никто не может гарантировать безопасность данных приложений.

Кроме того, без MMU немаловажным является и объем памяти. Своппинг исключается, и это тоже ограничивает возможности системы. Для серьезной системы даже 4 гигабайта линейной памяти не кажутся слишком большим объемом. EM64T спасет серьезные системы, если они без MMU всетаки возникнут.

Надо сказать что я не большой любитель систем с единым адресным пространством, имею ввиду Bluebottle и аналоги. Не смотря на горячие заверения приверженцем эти системы пока не нашли свое место в жизни и не доказали свою безопасность. Поэтому далее речь пойдет только о традиционных демократических системах. :)

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

Во первых это привязка приложения к положению в памяти. Конечно, при ограниченном количестве приложения их положение в памяти можно согласовать, но это слишком не гибко и не позволит приложениям использовать больше чем предначертано, не смотря на то, что остальная память может быть просто свободна. Самым правильным подходом будет перемещаемость приложений. Здесь тоже два варианта поведения. Либо PIC, либо перемещаемый формат. первый расходует больше памяти, второй больше времени. Если платформа маломощная - и то и другое может быть существенно. Но чтобы не изобретать велосипед, я думаю логичным было бы взять тот же ELF, и в перемещаемом формате загружать (и не изобретать BFLT).

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

Пока меня платформы без MMU не воодушевляют, есть дела поинтереснее, но не стоит зарекаться...

вторник, 26 февраля 2008 г.

Разворот стека методом трассировки кода (описание)

Предпринял попытку описать разворот стека методом трассировки кода, заодно проверил функционирование wiki на Google code. Они конечно хитрые, хранят wiki документы непосредственно в subversion репозитории. Портят мне логи, хотя по большому счету это разумный ход.

Это кстати новость. Перенес проект под Google code. Ну Subversion - он и в Африке Subversion, а вот Downloads сделан гораздо лучше. Да и wiki - это плюс. Что еще нужно от проектного хостинга по большому счету...

четверг, 21 февраля 2008 г.

Статическая гимнастика...

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

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

Способ первый:

#define STATIC_ASSERT(exp) extern char __static_assert[(exp) ? 1 : -1]

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

strict foo {...};
STATIC_ASSERT (sizeof (struct foo) == xxx);

Попытка объявить массив отрицательного размера вызывает массу ругани.

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

#define STATIC_ASSERT(exp) switch (0) { case 0: case ((exp) ? 1 : 0): break; }

Но такие ассерты ограничены в области применения. Их нельзя будет использовать за пределами функций. Думаю что так же не стоит пытаться оборачивать первый вариант традиционным для макросов do { } while (0), Это так же сократит возможности его использования.

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

Для большей наглядности вместо соответствующего стандарту си - assert(exp) создал STUB_ASSERT(exp, msg), который в случае нарушения ругается не просто выражениями, а целыми предложениями. Заодно можно держаться в ядре немного подальше от стандарта, чтобы не конфликтовать с ним.

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

#define assert(exp) STUB_ASSERT((exp) && 'FOOF', #exp)

Выражение 'FOOF' является допустимой для gcc многосимвольной константой, на которую выдается предупреждение 'Page.c:44:38: warning: multi-character character constant'. Можно конечно побаловаться с другими вариантами предупреждающих выражений, но в любом случае большой наглядности на этапе компиляции добиться не получится. Предупреждение и без того весьма примечательное.