Tworzenie aplikacji dla systemu operacyjnego QNX Neutrino
Transkrypt
Tworzenie aplikacji dla systemu operacyjnego QNX Neutrino
Max Hansen [email protected] Energy, Oil and Gas Industry Congo, Angola and Singapore Andrzej Rychlik Politechnika Radomska, Instytut Informatyczno-Techniczny Politechnika Łódzka, Instytut Informatyki Tworzenie aplikacji dla systemu operacyjnego QNX Neutrino Zintegrowane środowisko programistyczne (ang. Integrated Development Environment) to oprogramowanie udostępniające zestaw narzędzi i bibliotek służących do tworzenia, modyfikowania, testowania i konserwacji oprogramowania. W systemie QNX najpopularniejszym środowiskiem programistycznym jest Momentics IDE oparte o platformę Eclipse, działające w całości na Javie, a udostępniające programiście, m.in. możliwość kompilacji kodu pod wybrany procesor. Celem rozdziału jest przedstawienie procesu wytwarzania oprogramowania dla systemu QNX Neutrino, poczynając od prezentacji popularnych kompilatorów, a skupiając się głównie na tematyce wytwarzania w środowisku QNX Momentics IDE. Wprowadzenie do programowania dla QNX Neutrino Środowisk programistycznych dla systemu QNX jest wiele, jednak największą popularnością cieszy się zaledwie garstka. Najpopularniejszy multiplatformowy kompilator to CC i GCC wbudowany w system. Bardzo popularnym środowiskiem wykorzystującym GCC jest GNAT. Posiada on rozbudowany system testów ACATS, zaś źródłem dobrych przykładów na wykorzystanie w praktyce tego kompilatora może być strona http://www.ajam.org.pl/ programy/ gnat-examples.tar.bz2. Generalnie w systemie QNX praktycznie każde środowisko programistyczne oparte jest o kompilator GCC, który w zależności od parametrów potrafi obsługiwać różne języki programowania, poziomy optymalizacji, itp. QNX Neutrino i QNX Momentics IDE QNX to system czasu rzeczywistego, którego priorytetem jest bezpieczeństwo, w tym gwarancja wykonywania operacji w określonych ramach czasowych. W związku z tym istnieją odpowiednie zasady tworzenia oprogramowania dla tego systemu. Elementom tworzonego oprogramowania przypisuje się odpowiednie priorytety wykonywania, wedle których system będzie miał prawo na dopuszczanie opóźnień danego elementu, bądź tego prawa nie otrzyma. Dwa niezbędne składniki QNX Neutrino, traktowane łącznie jako jądro, objęte jedną nazwą „pronto”, to: mikrojądro systemu, będące modułem programowym dostarczającym elementarnych usług umożliwiających działanie procesów; 1 administrator procesów, czyli proces zarządzający pamięcią, przestrzenią nazw plików, czy procesami w systemie. Aby programować „pronto” niezbędna jest odpowiednia platforma programistyczna. Najlepszym rozwiązaniem na rynku cieszącym się coraz większą popularnością jest QNX Momentics. QNX Momentics zawiera w pakiecie system operacyjny QNX Neutrino, środowisko graficzne Photon, wraz z oprogramowaniem do tworzenia aplikacji okienkowych phAB, środowisko programistyczne IDE, narzędzia do pisania sterowników DDK, pakiety BSP, biblioteki i narzędzia GNU, instruktarzowe klipy wideo, obszerną dokumentację oraz szereg kodów. Pakiety BSP (Board Support Package) są zestawem narzędzi do uruchamiania systemu operacyjnego wraz z kompletną obsługą urządzeń docelowej platformy sprzętowej. Liczba zestawów wciąż rośnie, a dostępne są pod adresem: http://www.qnx.com/products/ ps_bsps. Przykładowy skrócony harmonogram tworzenia w QNX Momentics IDE oprogramowania dedykowanego: Utworzenie projektu i zaimportowanie do niego pakietów BSP ‘File’ > ‘Import’; Opisanie kodem i konfiguracja na bazie BSP; Budowanie projektu przez ‘make all’ zawarty w BSP; W rezultacie mamy bootowalny obraz systemu operacyjnego! Rys. 1. QNX Momentics IDE: Import pakietów źródłowych i BSP, krok 1 2 Wybieramy repozytorium źródeł BSP. Rys. 2. QNX Momentics IDE: Import pakietów źródłowych i BSP, krok 2 Zaznaczamy interesującą nas wersję pakietów BPS. Rys. 3. QNX Momentics IDE: Import pakietów źródłowych i BSP, krok 3. Wybieramy architekturę na jaką ma być zaimportowany BSP 3 Ustawienia projektu, w tym katalog docelowy, prefix. Rys. 4. QNX Momentics IDE: Import pakietów źródłowych i BSP, krok 4 Instalacja QNX Software Development Platform Do pracy nad projektem dla systemu QNX niezbędne jest odpowiednie środowisko programistyczne, jak QNX Software Development Platform. Ściągamy oprogramowanie ze strony http://www.qnx.com/download/feature.html?programid=21180, na której także wypełniamy formularz rejestracyjny. Otrzymamy na podany przez nas w formularzu adres email, podziękowania za ściągnięcie testowej wersji platformy deweloperskiej QNX oraz w chwilę później klucz licencyjny potrzebny do aktywacji testowej wersji oprogramowania. QNX Software Development Platform oferuje wersje dla różnych systemów operacyjnych jak Windows, Solaris, Linux, czy QNX Neutrino. Na potrzeby prezentacyjne wybieramy wersję oprogramowania pod Windows, zaczynając instalację od zatwierdzenia harmonogramu instalacyjnego QNX SDP. (Możliwość tworzenia oprogramowania w QNX SDP dla jądra QNX Neutrino w systemach Windows, Solaris, czy Linux umożliwia zmniejszenie kosztów wdrożenia narzędzi deweloperskich w firmach pracujących trwale w środowiskach Windows/Linux) 4 Rys. 5. Instalacja QNX SDP – rozpoczęcie instalacji Kolejnym krokiem jest wprowadzenie klucza produktu, który otrzymaliśmy po rejestracji na podany w formularzu adres email. Rys. 6. Instalacja QNX SDP wprowadzanie klucza produktu Aby kontynuować należy także zaakceptować warunki licencji. Rys. 7. Instalacja QNX SDP – akceptacja warunków licencji 5 Wybieramy ścieżkę, w której ma być zainstalowane oprogramowanie. Rys. 8. Instalacja QNX SDP – wybór ścieżki instalacji Zaznaczamy opcjonalne elementy produktu. Rys. 9. Instalacja QNX SDP – wybór opcjonalnych elementów Wyświetlone zostaje podsumowanie wybranych opcji do zatwierdzenia. Rys. 10. Instalacja QNX SDP – zatwierdzenie podsumowania 6 Rozpoczyna się proces instalacji. Rys. 11. Instalacja QNX SDP – proces ładowania środowiska Po instalacji otrzymujemy informację o lokalizacji przewodnika licencyjnego, po zatwierdzeniu, którego możemy rozpocząć pracę nad projektem. Rys. 12. Instalacja QNX SDP – informacja o pozytywnym ukończeniu instalacji Rys. 13. Instalacja QNX SDP – informacja o lokalizacji przewodnika licencyjnego Pierwsze uruchomienie QNX Momentics IDE 4.7 Przy pierwszym uruchomieniu QNX Momentics IDE ukazuje nam się zakładka ‘Welcome’ dostępna przy późniejszych próbach odsłony pod menu ‘Help’ > ‘Welcom’. 7 Rys. 14. Instalacja QNX SDP – Powitanie Zakładka oferuje bezpośredni dostęp do dokumentacji środowiska i języków programowania, wprowadzenie do środowiska, kursy, przykładowe małe projekty wdrożeniowe programisty oraz bezpośrednie przekierowanie do właściwej części środowiska, celem rozpoczęcia pracy nad projektem (tzw. Workbench). Rys. 15. Instalacja QNX SDP – Workbench starter Po kliknięciu opcji Workbench uruchomiona zostaje część właściwa środowiska. 8 Rys. 16. Instalacja QNX SDP – Workbench Tworzenie projektu w QNX Momentics IDE 4.7 Aby utworzyć nowy projekt C++, wybieramy ‘File’ > ‘New’ > ‘QNX C++ Project’ z głównego menu. Rys. 17. QNX SDP – Tworzenie projektu, krok 1 Nadajemy jakąś nazwę projektowi (np. ‘MyFirstProject’). 9 Rys. 18. QNX SDP – Tworzenie projektu, krok 2 W następnym kroku wybieramy architekturę procesora (zakładka ‘Build Variants), na którą będziemy tworzyć oprogramowanie (w naszym przypadku x86), klikając przycisk "Finish’ celem utworzenia szkieletu projektu. Rys. 19. QNX SDP – Tworzenie projektu, krok 3 Naszym oczom ukaże się prosty przykładowy kod, realizujący wyświetlenie na ekranie powitania w środowisku QNX Momentics IDE. #include <cstdlib> #include <iostream> int main(int argc, char *argv[ ]) { std::cout << "Welcome to the QNX Momentics IDE" << std::endl; return EXIT_SUCCESS; } Kompilacja, konsolidacja, uruchamianie w QNX Momentics IDE 4.7 Celem utworzenia plików wykonywalnych prawym przyciskiem myszy klikamy na nazwie projektu wybierając ‘Build Project’. W konsoli wyświetlone zostaną opcje z jakimi program został skompilowany i/lub ewentualne błędy kompilacji. 10 Rys. 20. QNX SDP – Logi procesów tworzenia Uruchamianie programu konfigurujemy po wyborze opcji ‘Run’ > ‘Run As’ > ‘C/C++ QNX application’ ustanawiając, m.in. argumenty uruchomieniowe, wirtualne środowisko w jakim projekt ma być uruchamiany, priorytet czy sposób kolejkowania. Rys. 21. QNX SDP – Konfiguracja uruchomieniowa projektu Po uzupełnieniu pól przede wszystkim w karcie Main, możemy uruchomić aplikację, czego rezultat obejrzymy w podglądzie konsoli. Tworzenie oprogramowania dla urządzeń wbudowanych QNX Momentics wspiera 3 nurty tworzenia oprogramowania: – self-hosted development Oprogramowanie tworzy się i uruchamia na tym samym komputerze. – cross-development Przygotowuje się oprogramowanie dla maszyny docelowej target innego typu niż maszyna deweloperska host. Główną i chyba najistotniejszą różnicą jest typ procesora w obu komputerach. – host-target development Oprogramowanie tworzy się na stacji zwanej hostem, a uruchamia na maszynie docelowej zwanej targetem. Metodą tą tworzy się oprogramowanie dla systemów wbudowanych, by uniknąć problemów związanych z różnicą architektury hosta i targetu. 11 Przykładowe problemy związane z różnicami architekturalnymi systemu hosta i systemu docelowego: za małe zasoby pamięciowe, procesorowe; brak, bądź zbyt ubogi interface; niewystarczające zasoby osprzętowe; brak wsparcia dla danych rozdzielczości. Celem uzyskania dostępu do systemu docelowego z IDE, należy utworzyć projekt docelowy (‘Target Project’), przez otwarcie perspektywy informacji systemowej: w menu okna ‘Open Perspective’ > ‘Other’ > ‘QNX System Information’. W pustym oknie ‘Target Navigator’ klikamy prawym przyciskiem myszy, po czym wybieramy ‘Ad New Target’. Wprowadzamy następnie nazwę systemu docelowego oraz jego adres IP. Jeśli docelowym systemem jest QNX Neutrino w konsoli ukaże się lista procesów uruchomionych w tymże systemie. Obsługa wątków W systemie QNX obsługa wątków realizowana jest przez mikrojądro. System zapewnia wszystkie procedury obsługi i synchronizacji wątków, dostarcza standardowego interfejsu wątków POSIX 1003.1. Tworzenie wątków w programach Neutrino jest bardzo proste. Wystarczy dołączyć bibliotekę pthread.h do nagłówka programu C/C++ i wykorzystać funkcje pthread_*(). Dołączanie nagłówka celem korzystania z wątków POSIX: #include <pthread.h> ... Przy kompilacji (dokładniej przy konsolidacji) należy dołączyć bibliotekę libc. Przykładowo, żeby skompilować program a.c należy wpisać: $ qcc a.c -l c Wszystkie funkcje oraz typy danych tworzące API wątków POSIX’owych mają nazwy rozpoczynające się od przedrostka pthread_. Wątki obiektowo Wątkowość bardzo słabo nadaje się do implementacji obiektowej. Wątki tworzone i wysyłane są w blokach kodowych, po czym dostarczane z wywołań zwrotnych funkcji do wykonywanych zadań. Taka kolej rzeczy wpływa na to, że programista sięga do zmiennych globalnych, powstają segmenty, całkowicie słabego jakościowo kodu. Tradycyjnie tworzenie i wysyłanie wątku wygląda mniej więcej tak: void * callback_function(void *object) { // Wykonywanie jakiegoś kodu } int main(int argc, char **argv) { ... int threadId; threadId = ThreadCreate(0, &callback_function, NULL, NULL); 12 ... } ThreadCreate jest funkcją, która tworzy i wysyła wątek. #include <sys/neutrino.h> int ThreadCreate( pid_t pid, void* (func)( void* ), void* arg, const struct _thread_attr* attr ); pid: tu używamy ID procesu, którym chcemy utworzyć wątek lub 0 by utworzyć wątek w aktualnym procesie. Przykład uproszczonego programu opartego o wątki: #include <pthread.h> //--------------------------------------------------------void * funcThreadA( void ) { int a_petla; for ( a_petla = 1; a_petla <= 20; a_petla++ ) { printf( "A\n" ); sleep( 1 ); // opoznienie } return; } //--------------------------------------------------------void * funcThreadB( void ) { int b_petla; for ( b_petla = 1; b_petla <= 10; b_petla++ ) { printf( "B\n" ); sleep( 2 ); } return; } //----------------------------------------------------------int main( void ) { pthread_t threadA; 13 pthread_t threadB; printf( "Startowanie glownego programu\n" ); /* Tworz watek, dodaj do istniejacego, pthread_create( &threadA, NULL, &funcThreadA, NULL ); pthread_create( &threadB, NULL, &funcThreadB, NULL ); printf( "Glowny program oczekuje..\n" ); pthread_join( threadA, NULL ); pthread_join( threadB, NULL ); printf( "Glowny program konczy\n" ); return 0; } wątku. Istnieje możliwość na znalezienie prostego rozwiązania obiektowego tworzenia class SomeClass { public: SomeClass() { ThreadCreate(0, &SomeClass::someMethod, NULL, NULL); } private: int someVariable; static void *someMethod(void *object) { SomeClass *classInstance = dynamic_cast<SomeClass*>(object); if (!classInstance) return NULL; while (!done) { if (somethingChanged) classInstance->someVariable++; } } }; Administracja procesami Procesy są podstawowymi składnikami budulcowymi każdej aplikacji systemów wielozadaniowych. W systemie QNX istnieje kilka metod tworzenia procesów. Metody tworzące procesy w systemie QNX to: fork() – tworzy proces potomny procesu macierzystego w formie kopii; exec*() – zastąpienie bieżącego procesu procesem utworzonym z podanego jako parametr funkcji pliku wykonywalnego; spawn*() – dają efekt wywołania sekwencji funkcji fork() i exec*(); system() – najprostsza metoda utworzenia procesu. Na zakończenie procesu powinny składać się następujące czynności: zakończenie komunikacji z innymi procesami; 14 zwolnienie zasobów zajmowanych przez proces; oczekiwanie na zakończenie procesów potomnych. Metody kończące procesy w systemie QNX to: exit() – powoduje zakończenie bieżącego procesu; wait(), waitpid() – wykorzystywane do synchronizacji zakończenia procesu; spawn*() – dają efekt wywołania sekwencji funkcji fork() i exec*(); system() – najprostsza metoda utworzenia procesu. Do kontroli procesów w systemie QNX wprowadzono odpowiednie limity, które można określać metodą setrlimit(), zaś testować metodą getrlimit(). Tab. 1. Zasoby systemowe podlegające ograniczeniu Oznaczenie RLIMIT_CORE Opis Pamięć operacyjna RLIMIT_CPU Czas procesora RLIMIT_DATA Wielkość pamięci pobranej ze sterty RLIMIT_FSIZE Max plik tworzony przez proces RLIMIT_NOFILE Max liczba deskryptorów plików tworzonych przez proces ELIMIT_STACK Maksymalny rozmiar stosu RLMIT_NPROC Maksymalna liczba procesów potomnych tworzonych przez proces Akcja przy przekroczeniu Zakończenie procesu Wysłanie sygnału SIGCPU do procesu przekraczającego zasób Funkcja pobierająca pamięć kończy się błędem Wysłanie sygnału SIGXFSZ do procesu przekraczającego zasób Funkcja tworząca ponad limitowe pliki zakończy się błędem Wysłanie sygnału SIGSEGV do procesu przekraczającego stos Procesy potomne przekraczające limit nie będą tworzone Celem kontrolowania danych procesów należy posługiwać się odpowiednimi atrybutami procesów. 15 Tab. 2. Atrybuty procesów w systemie QNX Atrybut procesu Identyfikator procesu PID Identyfikator procesu macierzystego PPID Numer grupy procesów PGID Identyfikator sesji SID Rzeczywisty identyfikator użytkownika UID Rzeczywisty identyfikator grupy GID Środowisko procesu Katalog bieżący Priorytet procesu Strategia szeregowania Testowanie getpid() getppid() getpgrp() getsid() getuid() getgid() getenv() getcwd() getprio(), sched_getparam() sched_getparam() Ustawianie setpgrp(), setpgid() setsid() putenv() chdir() setprio(), sched_setparam() sched_setparam() Zarządzanie procesami wiąże się z następującymi czynnościami: testowaniem i ustawianiem atrybutów procesu; tworzeniem i kończeniem procesu; synchronizacją zakończenia procesu potomnego z jego procesem macierzystym; testowaniem statusu zakończonego procesu potomnego. W systemach wielozadaniowych prawie zawsze istnieje pewien podzbiór procesów oddziaływującym na siebie. Źle zorganizowany dostęp do tych samych zasobów prowadzi do wielu problematycznych sytuacji. W systemach opartych o priorytety z możliwością wywłaszczania (w tym QNX), projektanci muszą wykazywać się szczególną ostrożnością. Najczęściej powstającym złym scenariuszem jest tworzenie procesów o wysokich priorytetach, przekazujących między sobą zasoby, a nie dopuszczających pozostałych procesów. Takie sytuacje doprowadzają do niemożliwości zakończenia zadań mniej priorytetowych, aczkolwiek nadal ważnych, nazywa się to „głodzeniem”, bądź „wykluczeniem”. Innym jeszcze gorszym problemem są zakleszczenia procesów lub inwersja priorytetów. Zakleszczenie procesów to sytuacja, w której dane procesy nawzajem blokują sobie wzajemnie zasoby systemowe. Przykładowo, istnieją w systemie 3 procesy, nazwijmy je P1, P2, P3 oraz docelowe zasoby zwane Z1, Z2, Z3. Proces P1 posiada Z1, lecz potrzebuje do działania również dostępu do Z2, zaś P2 nie może być wykonane, ponieważ potrzebuje dostępu do Z3, do tego jeśli P3 potrzebuje dostępu do Z1, zarezerwowanego przez P1 system potrzebuje jakichś określonych metod wykrywania sytuacji i limitów czasowych na jej blokowanie (algorytmy wykrywające zakleszczenie procesów opierają się o teorię grafów). Inwersja priorytetów polega na tym, że zadanie o niskim priorytecie zajmując zasób dzielony, zmusza zadanie o wyższym priorytecie do przejścia w stan „blokowane” i oczekiwania na zwolnienie tego zasobu. Taka sytuacja prowadzi do wielu 16 niebezpieczeństw, które w najgorszym wypadku mogą powodować powstanie sporych anomalii czasowych w systemie. System operacyjny QNX posiada sprawne systemy zarządzania procesami współbieżnymi, tj. nadawanie procesom priorytetów, wywłaszczanie procesów mniej priorytetowych, kolejkowanie procesów, zoptymalizowane czasowo przełączanie procesów. W systemie QNX priorytety, to liczby całkowite z zakresu 0-31 dla zadań super użytkownika lub 0-19 dla pozostałych. Wątki dziedziczą priorytet od swoich zadań macierzystych. Najniższy priorytet działa w tak zwanym tle (ang. idle), a jego wątki realizowane są wtedy, gdy w systemie nie ma nic innego „do roboty”. Zadanie idle jest zawsze gotowe do wykonania (ang. ready to run). Zadania uruchomione przez powłokę standardowo uzyskują priorytet 10. Każde zadanie, w oparciu o swój priorytet, trafia do odpowiedniej kolejki, tzw. FIFO (ang. First In First Out), działając wedle zasady „pierwszy przyszedł, pierwszy zostanie obsłużony”. System QNX dostarcza trzy algorytmy szeregowania procesów, które są używane, gdy istnieją równoważne priorytetowo zadania ubiegające się o procesor: Kolejka FIFO. Zadanie wybrane do wykonywania, kontynuuje swoje działania, aż samo odda sterowanie, np. procesowi systemowemu, zostanie wywłaszczone przez zadanie o wyższym priorytecie, bądź trwa do zakończenia. Algorytm karuzelowy, oparty o kolejkę FIFO, lecz z limitem czasowym, który wynosi 50 ms. Wówczas zadanie zostaje wywłaszczone, poza warunkami opisanymi we wcześniejszym algorytmie, również wtedy, kiedy wykorzysta przydzielony mu czas. Algorytm adaptacyjny (ang. adaptive scheduling), podobnie jak karuzelowy ograniczony kwantem czasu, lecz jeśli dane zadanie wykorzysta przydzielony czas procesora i nie zostanie zablokowane, to jego priorytet jest dekrementowany o jeden poziom, po czym po przebiegu każdej kolejnej sekundy oczekiwania na wykonanie podnoszony o jeden, lecz nie wyżej niż do stanu początkowego. Algorytm ten znajduje zastosowanie w sytuacjach, kiedy zadania wykonujące ogromne ilości obliczeń dzielą czas procesora z zadaniami interaktywnymi. Jest to domyślny algorytm dla programów uruchamianych przez powłokę. Algorytm szeregowania może być przyporządkowywany do zadania w sposób dynamiczny. Wybór konkretnego algorytmu szeregowania może być dokonywany przy pomocy funkcji POSIX takich jak: sched_getscheduler(), sched_set_scheduler(). Reasumując, podczas projektowania aplikacji działających w oparciu o priorytety należy trzymać się zasad bardzo starannego zarządzania zasobami, bowiem nawet te najlepsze metody zabezpieczeń systemowych niosą za sobą ryzyko krytycznych opóźnień systemu, utraty danych, bądź innych niekorzystnych sytuacji. Zadania powinny działać według określonych zasad: procesy zwalniają zasoby możliwie najszybciej; hierarchiczna organizacja zasobów; implementacja protokołu przydziału. 17 Błędy a QNX Neutrino Odnajdywanie błędów Ponieważ każdy program posiada błędy, nigdy nie ma pewności czy i kiedy otrzymamy zapytanie od użytkownika stworzonej przez nas aplikacji dlaczego po kilku dniach użytkowania program przestaje działać. Jeśli tak się stanie może to oznaczać, że nasz program generuje błędy, gdzieś w pamięci. Debugowanie błędów pamięciowych potrafi być irytujące, jednak na nasz ratunek przychodzi perspektywa analizy pamięci QNX. Ułatwieniem dla tejże perspektywy jest modułowa budowa systemu Neutrino, izolująca problematyczne procesy w systemie. Perspektywa analizy pamięci QNX pokazuje jak nasz program wykorzystuje pamięć pomagając upewnić się, że nie wywołuje problemów. Perspektywa ta pomaga szybko wskazać błędy pamięciowe naszego środowiska testowego przed tym jak nasz klient otrzyma produkt. Należy pamiętać jednak, iż perspektywa analizy pamięci potrafi dawać nieoczekiwane rezultaty, kiedy więcej niż jedno IDE komunikuje się z systemem docelowym. Tak więc do używania omawianej perspektywy należy zawsze mieć pewność, iż tylko jedno IDE jest podłączone pod system docelowy. Wycieki pamięciowe Wycieki pamięciowe polegają na nadmiernym zużywaniu pamięci przez aplikację, bądź próbie zapisu danych w niedozwolonym obszarze. Działania takie mogą być spowodowane przez alokację pamięci, która nie jest wolna, referencję na zły obszar pamięci, bądź nie zwalnianie pamięci przez programistę. Typową reakcją zabezpieczeń systemu przy wycieku aplikacji jest błąd krytyczny w momencie, gdy system identyfikuje próbę zapisu w chronionym obszarze. Nie ma jednak zabezpieczeń przed sytuacjami, gdzie programista nie zwalnia zarezerwowanej wcześniej pamięci. W takiej sytuacji, jeśli rezerwacja wywoływana jest na zasadzie aktualnych potrzeb automatycznie może dojść do sytuacji niekontrolowanego rozrastania się aplikacji w przestrzeni pamięciowej. (Sytuacje takie wyklucza Java, która zaopatrzona jest w tzw. garbage collection, działający na zasadzie regularnego sprawdzania i usuwania z pamięci niepotrzebnych elementów. Jednak języki programowania systemów specjalistycznych jak C/C++ wymuszają na programiście konieczność przykładania dodatkowej uwagi, co swoją drogą ma dobre strony pod kątem oszczędności zasobów. QNX Neutrino tropi zachowanie każdego programu oraz zarezerwowaną przez niego pamięć, więc kiedy nastąpi zawieszenie programu system przywróci całą pamięć przez niego zarezerwowaną, włączając tą utraconą przez wycieki. Jeśli nasz program ma poważny wyciek, bądź wyciek powolny, ale niezawieszający programu, może to prowadzić nawet do błędów głównych serwisów systemu. Następujące elementy edytora analizy pamięci mogą pomóc odnaleźć błędy i uporać się z nimi: Allocation tabs: pokazuje wszystkie instancje, w których nasz program alokuje, realokuje czy też zwalnia pamięć, co pozwala określić, które elementy zostały niepotrzebnie zarezerwowane w zły sposób. 18 Errors tabs: pokazuje wszystkie błędy pamięciowe, wliczając w to wycieki. Aby uruchomić program z analizą pamięci, należy we właściwościach aplikacji wybrać typ uruchamiania lub debbugowania, po czym odszukać opcje memory analisys. Literatura http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/ [dostęp [dostęp 22.05.2011] http://www.qnx.com/developers/docs/6.3.2/momentics/quickstart/about.html [dostęp 20.05.2011] http://www.qnx.com/developers/docs/6.3.2/photon/prog_guide/about.html [dostęp 23.05.2011] http://www.qnx.com/developers/docs/6.3.0SP3/ide_en/user_guide/concepts.html [dostęp 23.05.2011] http://psy.swan.ac.uk/staff/carter/qnx/tut_nto_thread_ab.htm [dostęp 10.06.2011] http://www.eetimes.com/design/embedded [dostęp 10.06.2011] http://www.se.rit.edu/~rtembed/QNX-tutorials/Guides/OOThreads-tutorial.pdf [dostęp 20.05.2011] Hansen M., Rychlik A.: Przeglad systemów operacyjnych w systemach bezpieczenstwa. [W:] Informatyka w dobie XXI wieku. Nauka, technika, edukacja a nowoczesne technologie informatyczne. Pod red. Aleksandra Jastriebowa i Marii Raczynskiej. Radom 2011 19