Вбудована система обробки текстової інформації
Дистрибутиви та особливості архітектури QNX, існуючі процеси та потоки, засоби та принципи синхронізації. Організація зв'язку між процесами. Алгоритм роботи системи та результати її тестування. Опис основних елементів програмного коду файлу code.c.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | украинский |
Дата добавления | 09.06.2015 |
Размер файла | 132,0 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Курсова робота
Вбудована система обробки текстової інформації
Вступ
програмний алгоритм синхронізація
QNX - це зареєстрована торгова марка фірми Quantum Software Systems, Canada. Фірма заснована в 1980 році. У той же самий час QNX - назва інтегрованої операційної системи, призначеної для підтримки роботи ЛВС у реальному масштабі часу і розробленою фірмою Quantum. В даний час QNX знаходить усе найбільш широкий попит на ринках Європи, Канади і США завдяки своїм унікальним властивостям. QNX - це багатозадачна багатокористувацька - операційна система, що працює на РС-совместительных комп'ютерах.
QNX - система реального часу, у якій реалізована концепція зв'язку між задачами на основі повідомлень, що посилаються від однієї задачі до іншої, причому задачі ці можуть знаходитися як на тому самому вузлі ЛВС, так і на різних. Реальний час і концепція зв'язку між задачами у виді повідомлень впливають на розроблювальне для QNX програмне забезпечення і на програміста, що прагне з максимальною вигодою використовувати переваги системи. У такий спосіб можна створювати загальні прикладні програми, що придатні для виконання в будь-якому операційному середовищі, але в той же час можна створювати і такі програми, для яких QNX буде найбільш придатним операційним середовищем. Закінчуючи огляд ОС QNX, варто додати, що названа ОС може працювати в режимі захисту пам'яті, включає такі стандарти як POSIX і IEEE, а розроблювачі продовжують поповнювати її новими продуктами і властивостями. QNX може в даний час функціонувати на машинах із процесорами від і8088 до і80486, включаючи PS/2. QNX підтримує 255 вузлів мережі (процесорів), що можуть спільно використовувати програми, файли і периферійні пристрої. QNX у середньому виконує операції в 20 разів швидше, ніж UNIX, забезпечуючи цілком роботу мережі, при цьому вона вимагає 140КБ оперативної пам'яті. QNX мається эмулятор РС-DOS.
У 1980 році студенти канадського Університету Ватерлоо Гордон Белл і Ден Додж закінчили вивчення базового курсу з розробки операційних систем, в ході якого вони створили основу ядра, здатного працювати в реальному часі. Розробники були переконані, що в їх продукті була комерційна потреба, і переїхали в місто Каната в провінції Онтаріо (місто високих технологій, іноді це місце називають північною Силіконовою долиною Канади) і заснували компанію Quantum Software Systems. У 1982 році була випущена перша версія QNX, що працює на платформі Intel 8088. Одне з перших застосувань QNX, що набули поширення, не відносилося до вбудованих систем - вона була обрана для власного комп'ютерного проекту Міністерства освіти Онтаріо, Unisys ICON. У ті роки QNX використовувалося в основному тільки для «великих» проектів, так як ядро, що має розмір 44 кілобайт, було занадто великим, щоб працювати на однокристальних чіпах того часу. У середині 1980-х років була випущена QNX 2. Завдяки своїй надійності, система мала завидну репутацію і отримала широке розповсюдження для управління промисловими машинами. QNX 2 і зараз іноді застосовується у відповідальних системах. У середині 1990-х в Quantum зрозуміли, що на ринку швидко завойовує популярність POSIX, і вирішили переписати ядро, щоб воно було більш сумісним на низькому рівні. Так з'явилася QNX 4. Вона була доступна з вбудованої графічної підсистемою, названої Photon microGUI, імпортований під QNX версією X Window System. Перенесення програм в QNX 4 з операційних систем, заснованих на Unix, стало набагато простіше, також були прибрані багато хто з «примх» більш ранніх версій. Також, на початку 1990-х компанія була перейменована в QNX Software Systems (QSS), щоб уникнути плутанини з іншими компаніями, в першу чергу з виробником жорстких дисків, які мають таке ж ім'я.
В кінці 1990-х було вирішено створити операційну систему, що відповідає свіжої редакції POSIX і в максимальному ступені сумісну з NetBSD та GNU / Linux, в той же час зберігши передбачувана поведінка і мікроядерну архітектуру. Результатом цих розробок стала QNX Neutrino, випущена в 2001 році. Ця версія поставляється разом з QNX Momentics Tool Suite, середовищем розробки програмного забезпечення (IDE), заснованої на Eclipse IDE, різними утилітами GNU і програмним забезпеченням, орієнтованим на Інтернет: веб-браузерами Voyager і Mozilla, а також веб-сервером. На відміну від попередніх версій, які працювали тільки в PC-сумісних архітектурах, QNX 6 легко адаптується практично до будь-якої конфігурації. Крім того, особливу увагу було приділено опрацюванню архітектури з тим, щоб її можна було ефективно масштабувати: як «вгору» (додаючи нові сервіси та розширюючи функціональність), так і «вниз» (урізуючи функціональність, щоб «втиснутися» в обмежені ресурси). Іншими словами, QNX 6 можна встановити там, де QNX 4 не вмістилася б. Також, в QNX 6 всі драйвери були приведені до єдиної моделі і всі інтерфейси стали відкритими.
27 жовтня 2004 компанія QSS була куплена міжнародною корпорацією Harman, активно працює на ринку мультимедійних пристроїв і систем автомобільної електроніки, але далекої від розробки ОС реального часу. При цьому Harman зберегла повну автономію компанії QSS, а генеральний директор компанії Ден Додж одночасно зайняв пост віце-президента корпорації Harman з інформаційних технологій. Після 2004 року інтерес у світі як до QNX, так і до конкуруючих продуктів, почав згасати. QNX зберегла популярність в основному в Японії, Німеччини, Росії та, останнім часом, у Китаї завдяки активному розвитку ринку автомобільної електроніки та інтегрованих систем управління виробництвом.
Восени 2007 року компанія QNX Software Systems приступила до поетапного відкриття вихідного коду QNX Neutrino на умовах ліцензії гібридного типу в рамках спільноти Foundry27. Ця ліцензія дозволяє ентузіастам безкоштовно отримувати доступ не тільки до вихідних текстів операційної системи, а й до інструментальних засобів. При цьому для комерційного використання QNX Neutrino як і раніше необхідно купувати відповідні ліцензії. Крім того, ліцензія QNX Neutrino прямо забороняє проведення сертифікацій продуктів, похідних від вихідного коду QNX Neutrino, без письмового дозволу компанії QSS. У вересні 2009 року на порталі Foundry27 був створений проект, призначений для супроводу QNX4 в публічній формі. 9 квітня 2010 канадська компанія Research In Motion, що володіє брендом BlackBerry, уклала угоду про викуп у компанії Harman International підрозділу, що займається розробкою QNX. У цей же день на сайті Foundry27, з'явилося оголошення, що доступ до вихідного коду QNX для широкої громадськості з цього моменту обмежений. 27 вересня 2010 на конференції BlackBerry DEVCON-2010 був представлений планшетний комп'ютер BlackBerry PlayBook c BlackBerry Tablet OS на основі QNX Neutrino.
1. Теоретична частина
1.1 Загальні положення
Під системою реального часу розуміється така інформаційна система, в якій коректність вихідної інформації залежить не тільки від правильності застосованих алгоритмів, а й від часу появи результатів обробки інформації. Тобто при запізненні результатів вони або можуть бути марними, або збитки в результаті запізнення можуть бути нескінченно великий.
Цей часовий критерій умовно розділив операційні системи на два класи - операційні системи загального призначення (General Purpose Operation Systems - GPOS) та операційні системи реального часу (Real Time Operation Systems - RTOS).
Основне завдання операційних систем загального призначення - ефективне розподіл ресурсів ЕОМ (таких як процесорний час, оперативна пам'ять та інші) між декількома програмами які одночасно виконуються. Такі операційні системи поставляються з багатим набором прикладних програм і мають розвинений графічний інтерфейс, що дозволяє користувачам працювати з додатками, не замислюючись над внутрішніми механізмами ОС.
А операційні системи реального часу (ОСРЧ) розробляються в розрахунку на наявність зовнішніх джерел даних. Основне завдання ОСРЧ - своєчасно обробити запит, всі інші аспекти функціонування ЕОМ відходять на другий план. Тому ОСРЧ поставляються в комплекті з різноманітними засобами розробки програм. Іншими словами, покупцями ОСРЧ є не кінцеві користувачі, а розробники програмного забезпечення.
Часто при розмові кажуть про операційні системи «м'якого» і «жорсткого» реального часу. ОС жорсткого реального часу гарантує виконання якихось дій за певний інтервал часу. А ОС м'якого реального часу, як правило, встигає виконати задані дії за заданий час. Тобто ОС м'якого реального часу виконує завдання з якимось значенням ймовірності.
QNX - це сімейство операційних систем жорсткого реального часу, орієнтованих головним чином на ринок вбудованих систем. Вона забезпечує всі невід'ємні складові системи реального часу: багатозадачність, диспетчеризацію програм на основі пріоритетів і швидке перемикання контексту. QNX - дивно гнучка система. Розробники легко можуть налаштувати операційну систему таким чином, щоб вона відповідала вимогам конкретних програм. QNX дозволяє створити систему, що використовує тільки необхідні для вирішення вашої задачі ресурси. Конфігурація системи може змінюватися в широкому діапазоні - від ядра з кількома невеликими модулями до повноцінної мережної системи, яка обслуговує сотні користувачів.
Таке призначення вимагає від ОС максимального використання особливостей апаратури. Тому ОС QNX різних версій, а точніше поколінь, не мають між собою двійковій сумісності. Звичайно, розробники при створенні нових «версій» QNX використовують кращі рішення з попередніх версій і залишаються вірними фундаментальним концепціям QNX. Для комерційного використання доступно три сімейства ОС QNX: QNX2, QNX4 і QNX6:
с ОС QNX 2 мало поширена в Україні. По-перше, до 1991 року система була заборонена до вивозу з Північної Америки як стратегічний ресурс. По-друге, ЕОМ на базі процесорів Intel 286 майже повсюдно вийшли з ужитку.
с ОС QNX 4 використовує захищений режим, тому може застосовуватися на процесорах не нижче Intel 386. QNX 4, мабуть, найпоширеніша на сьогоднішній день ОС QNX в промисловості. Остання її версія - 4.25 патч G (вийшла на початку 2003 року). Компанія QSS не розвиває цю ОС, але продовжує випускати до неї драйвера для нових пристроїв.
с ОС QNX 6 (або QNX Neutrino) завдяки цікавим і незвичайним архітектурним рішенням може використовуватися не тільки на х86-сумісних ЕОМ і ще більш зручна для вбудовування, ніж QNX 4. QNX Neutrino розробляється з повною підтримкою специфікацій POSIX, крім того, розробники системи прагнуть забезпечити максимальну переносимість в QNX вихідних кодів, написаних для ОС Linux. Це значно полегшує портування вільно поширюваного ПЗ в QNX і, з іншого боку, забезпечує «переносимість» для розробників - прикладний програміст, що знає будь-яку UNIX-подібну ОС, може приступати до розробки прикладного ПЗ для QNX без переучування. Остання версія QNX Neutrino - 6.3.
З точки зору QNX всі інстальовані копії ОС відносяться до двох категорій: інструментальні системи і цільові системи.
Інструментальна система (або середовище розробки) - це ЕОМ з засобами, що дозволяють формувати образ цільової системи. Такі кошти включені тільки в комерційні дистрибутиви пакету розробника QNX Momentics.
Цільова система (або середовище виконання) призначена для експлуатації. Середовище виконання фактично являє собою інструментальну систему, з якої видалено все непотрібне для даної прикладної задачі.
1.2 Дистрибутиви QNX
Дистрибутив - це спосіб поставки інструментальних систем. Іншими словами, QSS продає саме інструментарій розробки. Середовища виконання формуються розробником самостійно, але для поставки їх кому-небудь ще потрібно купівля ліцензій на відповідне число копій середовища виконання (їх називають «модулі Run-Time»). Така політика дозволяє істотно знизити вартість цільових систем.
Слід звернути увагу, що кошти розробки поставляються в чотирьох варіантах - для Microsoft Windows ХР, Sun Solaris (тільки для SRARC-версії), Linux і, зрозуміло, для QNX.
Цільові системи можуть генеруватися для декількох апаратних платформ (ARM, MIPS32, StrongARM, SH4, PowerPC, Xscale, x86). Цей список, ймовірно, буде поповнюватися.
Висуваючи на ринок ОС QNX 6, компанія QSS випустила два дистрибутива:
с QNX Real Time Platform (QNX RTP) - повнофункціональна середовище розробки; поширювалася безкоштовно для некомерційного використання. У разі комерційного використання системи розробник повинен був придбати відповідну ліцензію у QSS;
с QNX Networking Infrastructure Platform (QNX NIP) - чисто комерційний дистрибутив, що представляє собою розширення QNX RTP додатковими програмними пакетами, орієнтованими на виробників мережевого устаткування.
З виходом версії 6.2 компанія QNX QSS дещо змінила підхід до формування дистрибутивів. Пакет розробника, що включає в себе ОСРВ QNX, графічну середу Photon, інструменти розробки і різне додаткове ПЗ, отримав назву QNX Momentics. В даний час випущено кілька дистрибутивів QNX Momentics:
с Non-Commercial Edition (NC) - ознайомчий комплект розробника, безкоштовний для некомерційного використання;
с Standard Edition (SE) - пакет розробника, що дозволяє вести комерційну розробку ПЗ, в тому числі формувати цільові системи для різних платформ;
с Professional Edition (PE) - розширений пакет розробника, доповнений інтегрованим середовищем розробки QNX IDE, заснованої на технології Eclipse, а також розширеною базою прикладів у вихідних текстах і рядом додаткових компонентів.
Детальна інформація по комплектації дистрибутивів Momentics доступна як у QSS, так і у її партнерів. Професійний комплект QNX Momentics вважається базовим (тобто SE - фактично є урізаним РЕ). РЕ може доповнюватися пакетами розширення (Bundles) для різних цільових ринків.
Для доступу до багатьох розділів сайту qnx.com і громаді Foundry27 потрібна реєстрація. Реєстрація проста і не займає багато часу. Для реєстрації треба зайти на сайт www.qnx.com і перейти за посиланням Login, розташованої у верхньому правому куті. Після цього слід вибрати пункт New member? після чого відкриється форма реєстрації в нижній частині екрана. Тепер залишилося вказати e-mail, ввести та підтвердити пароль і натиснути кнопку Create Account. Для закінчення реєстрації знадобиться заповнити невелику анкету і отримати код підтвердження електронною поштою, який необхідно вказати у формі на наступній сторінці. На цьому реєстрація закінчується, тепер можна завантажити дистрибутив QNX.
Якщо лист з ліцензійним ключем буде втрачено, то його завжди можна буде подивитися в профілі на qnx.com.
1.3 Архітектура QNX
Архітектура - це те, чим QNX, незважаючи на велику зовнішню схожість, відрізняється від операційних систем сімейства UNIX. Саме архітектура робить QNX операційною системою жорсткого реального часу.
Центральним поняттям в QNX є мікроядро. Грубо кажучи, мікроядро (якраз його-то і звуть Neutrino) майже нічого само не робить, а є свого роду комутуючим елементом, до якого за допомогою додаткових програмних модулів додається та чи інша функціональність.
Мікроядро операційної системи QNX-6 реалізує основні сервіси операційної системи та багатопотоковість безпосередньо у мікроядрі, і тому такі сервіси доступні без наявності додаткових модулів. Мікроядро Neutrino підтримує такі сервіси (об'єкти):
с потоки;
с повідомлення;
с сигнали;
с годинник;
с таймери;
с програми обробки переривань;
с семафори;
с взаємно-виключні блокування (mutexes);
с умовні змінні (condvars);
с бар'єри.
Сервіси, які включені до складу мікроядра, обрані за коротким шляхом виконання. Інші сервіси, які потребують істотну роботу (наприклад завантаження процесу на виконання), реалізовані зовні мікроядра на різних процесах чи потоках. Так, менеджер процесів procnto розширює сервіс, наданий ядром Neutrino, забезпечуючи підтримку процесів, захист пам'яті та адміністрування області файлових шляхів, додаючи при цьому тільки 32 кілобайти коду.
При створенні системи реального часу часто є необхідним паралельне виконання декількох процедур водночас. В мікроядрі Neutrino паралелізм роботи досягається завдяки використанню моделі потоків за стандартом POSIX (Portable Operating System Interface for Unix), який визначає процес як контейнер, що містить в собі один чи більшу кількість потоків виконання.
Крім мікроядра в ОСРВ QNX є ще один важливий компонент - адміністратор процесів. Мікроядро Neutrino скомпоновано з адміністратором процесів в єдиний модуль procnto - головний (і єдиний безумовно необхідний) компонент QNX. Якщо нам треба, щоб система реально робила якусь роботу, ми повинні запустити процес, що виконує цю роботу. Програми, що реалізують сервісні функції, називають адміністраторами ресурсів. Є адміністратори ресурсів, що забезпечують доступ до дисків, мережі та інше. Всі ці програми пов'язані воєдино мікроядром і злагоджено взаємодіють за допомогою механізму повідомлень.
Слід зауважити, що існують різні додаткові варіанти модуля procnto (не кажучи про версії для різних процесорів):
с procnto-smp - варіант модуля procnto з підтримкою симетричної багатопроцесорності;
с procnto-instr - варіант модуля procnto, обладнаний засобами трасування подій;
с procnto-smp-instr.
Насправді функціональність ОС може розширюватися не тільки за допомогою процесів, але і за допомогою динамічно приєднуваних бібліотек (Dynamic Link Library, DLL). Правильніше буде сказати, що як функціональність ОС розширюється за допомогою процесів, так функціональність процесів розширюється за допомогою DLL. Більше того, адміністратор ресурсів може бути реалізований або як програма, або як DLL.
Таким чином, у загальному випадку QNX складається:
с з мікроядра Neutrino;
с адміністратора процесів;
с адміністратора ресурсів;
с прикладних програм.
1.4 Процеси та потоки в QNX
Процес (process) - це програма, що виконується. Процес (або «задача») включає код і дані програми, а також різну додаткову інформацію - змінні системного оточення і таке інше.
Крім процесу важливим поняттям є «потік управління» (thread, або просто «потік», раніше його іноді називали «ниткою»). Потік управління - це фрагмент процесу, що містить безперервну послідовність команд, які можуть виконуватися паралельно з іншими потоками того ж і інших процесів.
Процес є, по суті, контейнером потоків і містить мінімум один потік. Потік - це найменша одиниця, що підлягає виконанню і диспетчеризації.
В залежності від характеру розроблюваного додатку, потоки можуть виконуватися незалежно один від одного та без потреби зв'язуватися між собою, або вони можуть бути сильно зв'язані. Щоб забезпечити зв'язок і синхронізацію взаємодіючих потоків, Neutrino2 надає різноманітні сервіси IPC і синхронізації.
Для роботи з потоками існує бібліотека pthreads (потоки POSIX), яка не входить до складу мікроядра. Вони дуже корисні в ряді випадків, тому підтримка потоків - обов'язкова властивість POSIX-сумісних ОС.
В таблиці 1 подано POSIX-функції потоків, що входять до складу мікроядра.
Таблиця 1.
POSIX запит |
Запит мікроядра |
Опис |
|
pthread_create () |
ThreadCreate () |
Створити новий потік для виконання |
|
pthread_exit () |
ThreadDestroy () |
Знищити потік |
|
pthread_detach () |
ThreadDetach () |
Відокремити потік |
|
pthread_join () |
ThreadJoin () |
Приєднати до потоку, очікуючи його завершення |
|
pthread_cancel () |
ThreadCancel () |
Скасувати потік у точці скасування |
|
- |
ThreadCtl () |
Змінити Neutrino-визначені характеристики потоку |
|
pthread_mutex_init () |
SyncTypeCreate () |
Створити mutex |
|
pthread_mutex_destroy () |
SyncDestroy () |
Знищити mutex |
|
pthread_mutex_lock () |
SyncMutexLock () |
Блокувати mutex |
|
pthread_mutex_trylock () |
SyncMutexLock () |
Умовно блокувати mutex |
|
pthread_mutex_unlock () |
SyncMutexUnlock () |
Розблокувати mutex |
|
pthread_cond_init () |
SyncTypeCreate () |
Створити змінну умови |
|
pthread_cond_destroy () |
SyncDestroy () |
Знищити змінну умови |
|
pthread_cond_wait () |
SyncCondvarWait () |
Очікувати на змінну умови |
|
pthread_cond_signal () |
SyncCondvarSignal () |
Повідомити про змінну умови |
|
pthread_cond_broadcast () |
SyncCondvarSignal () |
Передати за сигналом змінну умови |
|
pthread_getschedparam () |
SchedGet () |
Одержати параметри диспетчеризації потоку |
|
pthread_setschedparam () |
SchedSet () |
Встановити параметри диспетчеризації потоку |
|
pthread_sigmask () |
SignalProcMask () |
Одержати або встановити маску сигналів потоку |
|
pthread_kill () |
SignalKill () |
Послати сигнал завершення потоку. |
Хоча потоки в межах процесу спільно використовують адресний простір процесу, кожен потік ще має й свої локальні дані. У деяких випадках ці дані захищені в межах ядра, у той час як інші локальні дані постійно знаходяться незахищеними в адресному просторі процесу. Нижче приведені деякі типи локальних ресурсів потоку:
с tid - кожен потік ідентифікований цілочисленим значенням, що починається з 1 і є унікальним у межах процесу, де існує потік;
с набір регістрів - кожен потік має свій власний лічильник програми, вказівник вершини стеку, і слово процесора;
с стек - кожен потік виконується в своєму власному стеку, збереженому в межах адресного простору його процесу;
с маска сигналу - кожен потік має власну маску сигналу.
Зазвичай потоки використовують:
с для розпаралелювання задачі на багатопроцесорних ЕОМ;
с для більш ефективного використання процесора (наприклад, коли один потік чекає користувача введення, інший може виконувати розрахунки);
с для полегшення спільного використання даних (всі потоки процесу мають вільний доступ до даних процесу).
1.5 Засоби синхронізації потоків
QNX-6 забезпечує POSIX-засоби синхронізації потоків, деякі з них можуть бути застосовні між потоками в різних процесах. Служби синхронізації вміщують наступне:
м'ютекси,
умовні змінні,
бар'єри,
sleepon-блокування,
блокування читання / запису,
семафори,
FIFO-планування,
передача / прийом/відповідь,
атомарні операції.
Взаємно-виключні блокування, чи м'ютекси, є найбільш простими засобами синхронізації. М'ютекс використовується, щоб гарантувати монопольний доступ до загальнодоступних між потоками даних. Тільки один потік може блокувати м'ютекс у будь-який даний час. Потоки, що намагаються блокувати вже блокований м'ютекс, блокуються. Коли потік розблокує м'ютекс, потік з вищим пріоритетом, що очікує м'ютекс, розблокується і стане новим власником м'ютексу. Таким чином, потоки будуть послідовно захоплювати м'ютекс через критичний інтервал часу в порядку пріоритетної черги.
Умовна змінна, чи condvar, використовується, щоб блокувати потік у межах критичної секції програмного коду, доки певна умова не буде задоволена. Умова може бути довільною.
Бар'єр - це механізм синхронізації, що дозволяє призупинити декілька потоків, змушуючи їх чекати у визначеній точці (біля «бар'єру»), доки таких потоків не набереться певне число. Коли зазначене число таких потоків, що чекають у бар'єра, набралося, вони усі розблокуються і можуть продовжувати далі своє виконання.
Sleepon-блокування схожі на condvar, з декількома розходженнями. Подібно condvar, sleepon блокування може використовуватися, щоб блокувати потік, доки певна умова не буде задовільнена. На відміну від condvar, sleepon-блокування мають «захований» м'ютекс, який програмно не доступний, і тому їх використання більш просте й надійне.
Блокування читання / запису використовуються для розв'язку проблеми «читач / письменник». Коли певний потік намагається записати дані до загальної області пам'яті, то за допомогою використання блокувань читання / запису його запит може бути відхилений, доки потік, що читає ці дані не розблокує її. Аналогічні дії можна виконати і при спробі читання під час запису даних іншим потоком.
Семафори аналогічні м'ютексам з тим розходженням, що доступ до ресурсу має не один потік, а кілька. Звільнення ресурсу збільшує семафор на одиницю, а захоплення - зменшує на одиницю. Якщо потік очікує на семафорі, що є позитивним, він не будете блокований. Чекання на не позитивному семафорі блокує, поки деякий інший потік не збільшує його. Семафори були визначені, щоб синхронізувати процеси. Для синхронізації між потоками в окремому процесі, м'ютекс буде більш ефективний, ніж семафори.
FIFO-алгоритм може гарантувати, що ніякі два потоки того ж самого пріоритету не виконають критичну секцію водночас. Усі FIFO-потоки в системі одного пріоритету будуть виконуватися по черзі, доки вони добровільно не звільнять процесор.
Передачі повідомлень Send/Receive/Reply здійснюють неявну синхронізацію за характером блокування. Це єдина синхронізація, що може використовуватися в мережі.
У деяких випадках необхідно виконати коротку операцію з гарантією, що операція не буде вивантажуватися іншим потоком чи програмою обробки переривання. Neutrino забезпечує атомарні операції для додавання значення, віднімання значення, очищення бітів, встановлення бітів.
1.6 Організація зв'язку між процесами
Мікроядро Neutrino2 пропонує наступні форми IPC:
с передача повідомлень,
с сигнали,
с черги повідомлень POSIX,
с загальнодоступна пам'ять,
с канали,
с FIFOs.
Потік, що виконує MsgSend(), надсилаючи повідомлення до іншого потоку (який може бути в межах іншого процесу), буде блокований, доки той інший потік не виконає MsgReceive(), обробить повідомлення, і не виконає MsgReply(). Якщо потік виконує MsgReceive() без попередньо посланого повідомлення, то він блокується, доки інший потік не виконує MsgSend(), тобто не надішле повідомлення (рис. 1).
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Рис. 1. Обмін повідомленнями між клієнтом та сервером
Це блокування синхронізує потік-відправник, що дозволяє серверу відповідати клієнту і продовжувати обробку, у той час як ядро асинхронно передає дані відповіді до потоку-відправника і позначають його як готовий до виконання. Функція MsgReply () використовується сервером для відповіді клієнту, щоб повернути нуль чи більшу кількість байтів, а функція MsgError () використовується, щоб повернути клієнту тільки стан. Обидві функції розблокують клієнта від його MsgSend ().
Служби передачі повідомлень копіюють повідомлення безпосереднє з адресного простору одного потоку до іншого без буферизації. Neutrino не аналізує зміст повідомлення - дані в повідомленні мають значення тільки для відправника й одержувача.
Для простих повідомлень Neutrino забезпечує функції, що беруть вказівник безпосередньо на буфер без потреби в IOV (Input-Output Vector - вектор введення / виведення).
У Neutrino передача повідомлень спрямована скоріше до каналів і підключень, ніж безпосередньо від потоку до потоку. Потік, що бажає одержати повідомлення, спочатку створює канал; інший потік, що бажає послати повідомлення першому потоку, повинен спочатку створити підключення, приєднуючись до створеного каналу.
Як тільки підключення встановлені, клієнти можуть виконувати MsgSend(). Якщо багато потоків у процесі прикріплюються на той же самий канал, то одне підключення буде розподілено між усіма потоками. Канали і підключення в межах процесу мають цілочисловий ідентифікатор. Клієнтські підключення відображаються безпосередньо в дескриптори файлів.
Додатково до синхронних Send/Receive/Reply служб, Neutrino також підтримує передачу повідомлень фіксованого розміру без блокування його відправника. Вони визначені як імпульси і мають чотири байти даних плюс один байт коду. Імпульси часто використовуються як механізм повідомлення в межах програм обробки переривань. Вони також дозволяють серверам відповідати клієнтам без їхнього блокування.
Передача повідомлень API (Інтерфейс прикладної програми) складається з наступних функцій (табл. 2).
Таблиця 2.
Функція |
Опис |
|
MsgSend() |
Надіслати повідомлення і заблокуватися до отримання відповіді |
|
MsgReceive() |
Очікувати на повідомлення |
|
MsgReceivePulse() |
Очікувати на импульс |
|
MsgReply() |
Відповісти на повідомлення |
|
MsgError() |
Відповісти тільки зі станом помилки. |
|
MsgRead() |
Читати додаткові дані від отриманого повідомлення |
|
MsgWrite() |
Записати додаткові дані до повідомлення відповіді |
|
MsgInfo() |
Одержати інформацію про отримане повідомлення |
|
MsgSendPulse() |
Надіслати імпульс |
|
MsgDeliverEvent() |
Надіслати клієнту подію |
|
MsgKeyData() |
Повідомлення перевірки ключа |
Стандарт POSIX визначає набір неблокуючих засобів передачі повідомлень, відомих як черги повідомлень. На відміну від примітивів передачі повідомлень Neutrino2, черги повідомлень постійно знаходяться поза ядром. Черги повідомлень здійснюють проміжне накопичення повідомлень, вони існують незалежно від процесів, що їх використовують. В Neutrino2 створені черги повідомлення будуть з'являтися в просторі імен файлів у каталозі /dev/mqueue.
Загальнодоступна пам'ять пропонує процесам використовувати вказівники, щоб безпосередньо читати і записувати в неї. Загальнодоступна пам'ять часто використовується разом з одним із примітивів синхронізації, щоб зробити модифікації даних атомарними. Загальнодоступна пам'ять найбільш ефективна, коли використовується для модифікування великої кількості даних. Семафори і м'ютекси - придатні примітиви синхронізації для використання їх з загальнодоступною пам'яттю. Загальнодоступна пам'ять реалізована в Neutrino у менеджері процесів (procnto).
Канал - це безіменний файл, що служить як канал введення / виведення між двома чи більше процесами, коли один процес записує в канал, а інший читає з каналу. Менеджер каналу забезпечує буферизацію даних. Канал буде вилучений, як тільки обоє його кінці закрилися. Канали звичайно використовуються, коли два процеси хочуть працювати паралельно з даними, що переміщаються від одного процесу до іншого в одному напрямку.
FIFOs - це ті ж самі канали, за винятком того, що вони є постійними файлами, які збережені в filesystem каталогах.
2. Практична частина
2.1 Алгоритм роботи системи
Головний потік створює два потока «читачі» та потік «письменник» який блокує MUTEX, зчитує та зберігає текст і запускає таймер.
Потоки «читачі» по черзі зчитують текст і виводять відповідну його частину.
Головний потік та інші потоки зупиняються за допомогою системного переривання від таймера.
2.2 Результати тестування системи
Під час виконання курсового проекту було написане на мові високого рівня програмування С. Компіляція файлів server.c, client.c, зміст котрих представлений у розділі «додатки» даного проекта, була здійснена за допомогою компілятора gcc, що є частиною дистрибутива операційної системи QNX.
Тестування системи виконується наступним чином:
Запускаємо програму, вводимо текст та натискаємо Enter, після чого потоки «читачі» починають його зчитувати і виводити. Перший потік вибере з усього тексту лише цифри, а другий - лише літери. Роботу програми ілюстровано на рисунку 2.
Рис. 2. Представлення роботи програми
2.3 Опис основних елементів програмного коду файлу code.c
volatile int data_ready = 0 - змінна для контролю read-write доступу. Ключове слово volatile вказує, що поле може бути змінене декількома потоками, що виконуються одночасно. Поля, оголошені як volatile, не проходять оптимізацію компілятором, яка передбачає доступ за допомогою окремого потоку. Це гарантує наявність найбільш актуального значення в поле в будь-який час. Як правило, модифікатор volatile використовується для поля, звернення до якого виконується через декілька потоків без використання оператора lock для серіалізациі доступу.
void * writter (void *arg) - функція «письменник» відповідає за запис тексту в область пам'яті. Отримує аргументом текст з клавіатури, та використовує MUTEX для контролю запису в область пам'яті. Виділяє в пам'яті місце під текст та вносить текст в цю пам'ять. Створює, ініціює та запускає таймер, який завершує потік - письменник та потоки - читачі.
arg = malloc (sizeof(str)) - елемент функції - письменника, виділяє пам'ять розміром sizeof(str).
strcpy (arg, str) - переносить значення str в область пам`яті arg.
timer_create (CLOCK_REALTIME, NULL, &timerid) - створює новий таймер.
timer_settime (timerid, 0, &value, NULL) - встановлює час тайм-ауту.
pthread_sleepon_lock() - Pthread_sleepon_lock () викликає pthread_mutex_lock () для мьютекса, який знаходиться в класі pthread_sleepon*. Ця функція викликається перед перевіркою умови, які визначають, чи потрібно викликати pthread_sleepon_wait (), pthread_sleepon_signal (), або pthread_sleepon_broadcast (). Це мьютекс не дозволяє іншим потокам змінювати дані поки з ними працює поточний потік.
Pthread_sleepon_signal () - функція розблокує найвищий пріоритетом потоки, які очікують на адресу.
Pthread_sleepon_unlock () викликає pthread_mutex_unlock () длямьютекса пов'язаного з pthread_sleepon * () класом функцій
void * reader_num (void *arg) - функція-читач, зчитує текст з області пам'яті, виявляє наявність цифер в тексті, друкує їх на екран
if ((char) str[i] >= '0' && (char) str[i] <= '9') - умова перевірки знаку на належність до цифр, використовує ASCII - код для визначення символу
sched_yield() - Процес може звільнити процесор без блокування, викликавши sched_yield. Процес буде переміщений в кінець черги процесів з однаковим статичним пріоритетом, і управління будепередано іншому процесу. Зауваження: якщо поточний процес є єдиним в черзі процесів з тим же пріоритетом, то він продовжить роботу відразу після виклику функції sched_yield. УPOSIX-системах, в яких існує функція а саме в <unistd.h>, задається визначення _POSIX_PRIORITY_SCHEDULING
while (data_ready!= 1) {pthread_sleepon_wait (&data_ready);} - реалізація очікування сигналу від потоку-письменника для доступу до тексту в область пам'яті.
void * reader_let (void *arg) функція-читач, зчитує текст з області пам'яті, виявляє наявність букв в тексті, друкує їх на екран if (((char) str[i] >= 'a' && (char) str[i] <= 'z') || ((char) str[i] >= 'A' && (char) str[i] <= 'Z')) - перевірка на належність символу до букв, використовується ASCII - код символу
int main() - головня функція програми
char str[65535] = «» - створення типу текстового типу даних для передачі потоку - письменнику, який занесе цей текст в память
gets(str); - зчитує введені знаки в змінну str
result = pthread_create (&thread1, NULL, writter, &str); - створення потоку-письменника
Pthread_create () функція використовується, щоб створитинову потік, з атрибутами зазначеними в Attr, в рамках процесу. Якщо Attr є NULL, за замовчуванням використовуються стандартні арибути. Якщо атрибути, зазначені в Attr були змінені пізніше, атрибути потоку не змінюються. Приуспішному завершенні pthread_create () зберігає ідентифікатор створеного потоку в місці зазаначеному потоком.
Потік створюється з виконанням start_routine аргументу в якості єдиного аргументу. Якщо start_routine повертається, ефект ніби був неявний виклик pthread_exit () за допомогою значення, що повертається start_routine як статус виходу. Потік, в якому main() спочатку викликається відрізняється від цього. Коли він повертається з main (), ефект аналогічний виклику exit() за допомогою значення, що повертається main() в якості виходу.
Сигнал стану нового потіку ініціалізується таким чином:
Сигнал маска успадковується від створеного потоку.
Набір сигналів в очікуванні для нового потоку порожній.
Якщо pthread_create () зазнає невдачі, новий потік не створюється, змінна потоку залишається невизначеною
result = pthread_create (&thread2, NULL, reader_num, &str); - створення потоку для читача 1
result = pthread_create (&thread3, NULL, reader_let, &str); - створення потоку для читача 2
result = pthread_join (thread1, NULL); - Функція pthread_join блокує роботу потоку що викликала його виконання до завершення thread'а з ідентифікатором thread.Після розблокування в покажчик, розташований за адресою status_addr, заноситься адреса, який повернув зупинений thread або при виході з асоційованою з ним функції, або привиконанні функції pthread_exit (). Якщо нас не цікавить, що повернула нам нитку виконання, як цього параметра можна використовувати значення NULL. Функція повертає значення 0 при успішному завершенні. Увипадку помилки повертається позитивне значення (а ненегативне, як в більшості системних викликів і функцій!), яке визначає код помилки, описаний у файлі errno.h. Значеннясистемної змінної errno при цьому не встановлюється.
result = pthread_join (thread2, NULL); - приєднання до потоку - читача 2
result = pthread_join (thread3, NULL); - приєднання до потоку - читача 2
free(str); - вивільнення памяті, виділеної під текст.
Висновки
В результаті виконання курсової роботи в операційній системі QNX 6.5 була розроблена вбудована система.
Була розроблена програма (головній потік) яка створює та записує на виконання три потоки, де перший потік («письменник»), запам'ятовує цей текст в буферній області пам'яті, а другий та третій потоки («читачі») зчитують з цієї області пам'яті, причому другий потік зчитує тільки літери, а третій потік - тільки цифри.
Література
Роб Кертен «Введение в QNX/Neutrino
Руководство по программированию приложений реального времени в QNX Realtime Platform», - ООО «Издательство Петрополис», 2001. - 480 с.
Сергій Зиль «Операционная система реального времени QNX от теории к практике» друге выдання
Додаток
#include <sys/neutrino.h>
#include <sys/netmgr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
volatile int data_ready = 0; //var for read-write lock
void * writter (void *arg) {
char* str;
str = arg;
arg = malloc (sizeof(str)); //new memory for variable
strcpy (arg, str); //copy string to memory
timer_t timerid;
struct itimerspec value;
value.it_value.tv_sec = 10;
timer_create (CLOCK_REALTIME, NULL, &timerid); //new timer
timer_settime (timerid, 0, &value, NULL); //set timer
while(1) {
if (data_ready == 0) {
pthread_sleepon_lock(); //lock thread
data_ready = 1;
pthread_sleepon_signal (&data_ready); //send signal
pthread_sleepon_unlock();} //unlock thread
}
}
void * reader_num (void *arg) {
int i;
char* str;
//while(1) {
pthread_sleepon_lock(); //thread lock
while (data_ready!= 1)
{pthread_sleepon_wait (&data_ready); //wait for signal
}
str = arg;
printf («Reader for number:»);
for (i = 0; i < strlen(str); i++) //for all string
if ((char) str[i] >= '0' && (char) str[i] <= '9') //check numbers
printf («%c», (char) str[i]);
printf («\n»);
data_ready = 0; //switch flag
pthread_sleepon_unlock(); //unlock thread
sched_yield(); //yield for second thread
}
// }
void * reader_let (void *arg) {
int i;
char* str;
//while(1) {
pthread_sleepon_lock();
while (data_ready!= 1)
{pthread_sleepon_wait (&data_ready);
}
str = arg;
printf («Reader for leter:»);
for (i = 0; i < strlen(str); i++)
if (((char) str[i] >= 'a' && (char) str[i] <= 'z') || ((char) str[i] >= 'A' && (char) str[i] <= 'Z'))
printf («%c», (char) str[i]);
printf («\n»);
data_ready = 0;
pthread_sleepon_unlock();
sched_yield();
}
// }
int main()
{
printf («Enter string:»);
char str[65535] = «»;
gets(str);
int id, result;
pthread_t thread1, thread2, thread3;
result = pthread_create (&thread1, NULL, writter, &str); //new thread
result = pthread_create (&thread2, NULL, reader_num, &str);
result = pthread_create (&thread3, NULL, reader_let, &str);
result = pthread_join (thread1, NULL); //join thread until thread death
result = pthread_join (thread2, NULL);
result = pthread_join (thread3, NULL);
free(str);
}
Размещено на Allbest.ru
Подобные документы
Характеристика дослідження методу введення обмежених обсягів текстової інформації в ЕОМ. Аналіз механізму розробки програми, що передбачає можливість запису текстової інформації до файлу, а також завантаження тексту з файлу. Порядок роботи з програмою.
курсовая работа [74,1 K], добавлен 05.02.2010Опис результату розробки архітектури пристрою та його структурної схеми на рівні міжрегістрових передач. Система для виконання тестування пристрою, результати його симуляції у формі часових діаграм. Cинтез розробленої VHDL-моделі пристрою в ПЛІС.
курсовая работа [1,2 M], добавлен 03.03.2015Вивчення існуючих систем по виявленню плагіату. Алгоритм створення системи для виявлення плагіату, в базі якої будуть зберігатися всі лабораторні роботи студентів. Проектування програми: побудова uml-діаграм, видалення коментарів в коді, опис архітектури.
дипломная работа [4,1 M], добавлен 09.06.2012Створення програми, що видає результати голосування та підсумки виборів. Алгоритм розробки програми. Опис структури даних та вимоги до них, стандартних процедур та функцій, файлів та їх призначення. Приклад тестування та результати роботи програми.
курсовая работа [1,0 M], добавлен 28.06.2012Огляд засобів створення програмного забезпечення сучасних мікроконтролерів. Аналіз методів та налаштувань контролерів. Засоби генерації коду налаштувань. Детальний опис розробки програми генератора налаштувань ядра Cortex M4 та методики її тестування.
курсовая работа [1,3 M], добавлен 20.05.2015Характеристика функціональної структури предметної області програмного комплексу. Розробка архітектури програмної системи. Вибір типу архітектури й зразків проектування. Опис декомпозиції, залежностей та інтерфейсу. Детальне проектування модулів та даних.
курсовая работа [462,2 K], добавлен 19.12.2013Проблеми процесу тестування програмного забезпечення. Розробка алгоритму автоматичної генерації тестів і тестового набору для ручного виконання. Побудова тестів для системи "Банкомат" і для баг-трекінгової системи, представленої графом із циклами.
дипломная работа [1,2 M], добавлен 26.02.2014Дослідження алгоритму роботи та коду програми. Оцінка методом "чорного ящика". Тестування і налагодження розробленої програми на алгоритмічній мові високого рівня. Оцінювання якості програмного забезпечення за об’єктно-орієнтованими метриками зв’язності.
курсовая работа [143,1 K], добавлен 11.03.2021Розробка логічної гри "Тетріс" у складі набору об’єктно-орієнтованих моделей, програмного коду з використанням об’єктно-орієнтованної мови Java. Проектування архітектури гри, аналіз вимог до неї, опис реалізації, кодування та тестування програми.
курсовая работа [2,2 M], добавлен 24.10.2010Опис методів і алгоритмів вирішення задачі в середовищі розробки Myeclipse. Основні функції програмного продукту, його структура. Розробка алгоритму та програми, інструкція користувачу. Результати тестування, лістинг основних блоків. Вікно головного меню.
курсовая работа [1,8 M], добавлен 24.02.2014