2004 г.
Особенности программирования BeOS API для пришельцев - введение. Часть 2-я.
Сергей Долгов, www.qube.ru
В прошлый раз мы остановились на обещании рассказать про main() и be_app.
И хотя данный цикл заметок не предполагает рассказать про все-все-все сразу, но у некоторых читателей может возникнуть желание тут же начать переводить всю эту премудрость в код. Поэтому надо указать на необходимые инструменты.
Отступление 1 - Инструменты.
Для аскетичных пришельцев-радикалов из мира юникс, достаточно будет следующих сведений:
Имеется vim. И ряд других редакторов консольного режима.
Шаблон makefile для BeOS находится в /boot/develop/etc/.
Имеются версии gcc - 2.9 и 2.95*. 3-й gcc можно собрать, но применять не получится из-за ABI.
Функции уровня POSIX находятся в libroot.so (glibc+libm+еще что-то, хотя не полностью).
Библиотека стандартных классов С++ - libstdc++.r4.so.
Значительная часть BeOS API, прежде всего интерфейсная - в libbe.so.
Для менее радикальных отмечу, что можно использовать GUI-редакторы Pe (http://bebits.com/app/3356), Eddie (http://bebits.com/app/95) и BeIDE - /boot/develop/BeIDE/BeIDE.
Последнее - это стандартная для BeOS интегрированная среда разработки (от Metrowerks), проект-ориентированная, но позволяет, для пуристов, генерировать и make-файлы из проекта.
Она же рекомендуется и тем новичкам в BeOS, кто привык разрабатывать программы в более современных средах.
Инструменты Быстрой Разработки Приложений (RAD) - BeXL, MeTOS, VisualBe, BeBuilder - на этом этапе категорически не рекомендуются.
Может быть рекомендована добавка к BeIDE - Don'tWorry(http://bebits.com/app/2374) - помогает в изучении иерархии классов.
Тем, кто привык к IDE, освоить BeIDE будет легко, впрочем, несколько замечаний необходимы:
1)Файлы BeOS-проектов имеют расширение *.proj. Для создания своего проекта, создайте сначала новую папочку и скопируйте туда файл(ы) из /boot/develop/BeIDE/stationery/x86/BeApp/ - это шаблон стандартного BeOS-проекта. Их можно переименовать под ваш проект. Запустите BeIDE двойным щелчком на proj-файле.
Впрочем, можно и просто запустить BeIDE, cоздать "новый проект" и выбрать тип шаблона прямо изнутри BeIDE.
2)А теперь не стоит сразу переходить на "русский народный" по поводу "диких" клавиатурных сочетаний (шорткатов) - они все настраиваются под ваш вкус в окне проекта - Edit->Preferences->General->KeyBindings. Цвета настраиваются в Edit->Preferences->Editor->SyntaxStyling.
Для тех же, кто не боится "Читать Эти Грёбаные Руководства" (RTFM) - есть мануал BeIDE от Metrowerks
Теперь, когда мы знаем, чем писать программы, можно открыть Главный Секрет "как писать" - каждая программа должна иметь начало. Менее главный секрет - программа в BeOS, как и любая другая С и С++ программа, начинается с выполнения функции main().
Никаких особых подвохов тут нет, единственно, что можно заметить на будущее, если программу запускать из командной строки с аргументами, то эти аргументы могут быть считаны не только традиционным способом в качестве параметров main() - argc и argv, но также и получены BeOS-приложением более натуральным для BeOS способом - через сообщение главному циклу сообщений (Message Loop) BeOS-программы. Такое сообщение отправляется AppServer-ом автоматически, при наличии этих самых аргументов.
Еще стоит отметить, что в GUI-шных BeOS-программах код в самой main обычно крайне минималистичен, и предназначен, главным образом, для запуска BeOS Application (наследник класса BApplication )- по сути того самого главного Message Loop. К сожалению, рассказать, что такое классы и что такое сообщения одновременно - довольно затруднительно, поэтому начну с сообщений.
Отступление 2. Сообщения - отправители, диспетчеры, обработчики, прерывания.
В первой части введения мы уже задавались вопросом - как это все программы умудряются работать одновременно? - и частично на него ответили. Необъясненным осталось то, как же всё-таки все эти куски, которые считают, что каждый из них - чуть ли не единственный на белом свете, взаимодействуют с друг другом в многозадачной операционной системе.
Ответ простой - они обмениваются телеграммами/письмами/SMS-ками/бандеролями/и даже грузовыми контейнерами:) - т.е. сообщениями (в unix-мире больше распространена концепция сигналов - signals, в BeOS signals реализованы в слое эмуляции POSIX).
Щелкнул мышкой - драйвер сработал, послал сообщение InputServer-у, тот - ApplicationServer-у, AppServer - в свою очередь - программе.
Хочет программа что либо нарисовать - сообщение AppServer-у, а уж доля того - общаться с драйверами видеокарты.
Соответственно, у всех жильцов в общежитии операционной системы должны быть способности к
1)отправке сообщений - отправитель в BeOS "называется" BMessenger,
2)приему-перехвату сообщений и решению, что с ними дальше делать (диспетчеризация) - этим занимается цикл приема и распределения сообщений - message loop, BLooper в BeOS,
3)обработке сообщений (обработчик по английски - handler) - BHandler в BeOS.
(Как вы могли догадаться, названия компонент-классов BeAPI начинаются с 'B'.)
Теперь немножко о самих BeOS-сообщениях, для тех знатоков, кто сталкивался с сообщениями в других ОС/платформах. Их отличительное качество - практически "свободный" формат. Единственный обязательный член BMessage - признак "ЧТО" (what). Например, если в сообщении, полученном BeOS-приложением этот what==B_ARGV_RECEIVED (константа, определенная в системе) - это означает, что программа была запущена из командной строки и там имеются аргументы - см. параграф про main().
А дальше (я не зря упомянул не только телеграммы, но и бандероли, и грузовые контейнеры) - в теле сообщения может содержаться практически все что угодно, любого размера. В теории - хоть DVD-диск упакуй туда. Но не рекомендую:)
Раз уж мы вдарились в объяснения, как работает многозадачная/многопоточная OS, можно спуститься поближе к земле, то есть к кремнию и железу, и пояснить, на чем все это основано. То есть, рассказать о прерываниях. Знатоки, а также ленивые и нелюбопытные могут смело пропустить нижеследующее безо всякого ущерба.
Есть два способа реагировать на изменения в обстановке - программный опрос (polling) и прерывания (interrupts).
Первый - это когда программа состоит из ужасных запутанных циклов, проверяющих по кругу состояния всего и вся - портов устройств, программ, системного таймера (чтобы время от времени переключаться между программами). На вид просто, с этого народ обычно начинает писать программы, на деле, написать ОС, работающую таким способом - надо быть крутым садомазохистом.
Это как если бы телефонная связь работала по тому принципу, что вам надо было бы раз в секунду подбегать к трубке и слушать, не пытается ли кто с вами пообщаться.
Второй - прерывания. Когда какому-нибудь устройству или программе невтерпеж пообщаться (например, буфер последовательного порта уже почти забит данными из модема) - они "звонят" процессору - выставляют запрос на прерывание, тот самый печально известный IRQ (interrupt request). Дальше начинается некоторая машинерия - кого обслужить первым и т.д., но, в конечном счете, запоминается текущее состояние системы, выполнение предыдущих программ прекращается (откладывается), и система переходит на выполнение кода, указанного в запросе на прерывание.
После удовлетворения потребности в тусовке, система возвращается к выполнению отложенных задач.
Так вот, и разделение времени между программами из первого объяснения про многозадачность, и создание/перехват/обработка сообщений из второго, происходят при помощи прерываний.
Для первого используются прерывания от системного таймера, для второго - используются так называемые программные прерывания. Аналогию с телефоном/пэйджером/SMS можете додумать сами :)
Теперь читатель знает почти достаточно, чтобы показать ему, как выглядит запуск BeOS-программы.
А выглядит он, в сокращенном виде, так:
--------------------------------
main()
{
KrutajaProgramma.Run()
-------------------------------
или так:
main()
{
SuperPuperProgramma->Run()
--------------------------------
Этот Run() - метод класса BApplication, запускающий главный цикл - приемник/диспетчер/обработчик сообщений для BeOS-программы в целом.
Охх, опять эти грабли, это "знает почти достаточно" - классы, методы, энкапсуляция, наследование, полиморфизм и прочие ругательства...боюсь что начало этого цикла статей так и будет состоять из сплошных отступлений. Может, отложим до завтра?:) Да и караул уже устал.
Разве что сейчас можно упомнять для знатоков, что be_app из предыдущей главки - это глобальный (доступный всем компонентам программы) указатель на объект этой программы. Переменная с таким именем создается автоматически, при создании объекта-наследника BApplication.
(В данном случае be_app == SuperPuperProgramma или be_app == &KrutajaProgramma).
А в связи с отступлением про сообщения, надо упомянуть также то, что BApplication является наследником BLooper и BHandler.
А для тех, кто не устал и полон энтузиазма запустить свою первую BeOS-программу - может прочитать статейку с кодом HelloWorld от Эрика Шеперда и Макса "Базы" Базарова.
Назад Далее