Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałStefcia Madejski Został zmieniony 10 lat temu
1
Automatyka i Robotyka Systemy czasu rzeczywistego Wykład 3
2
Typy procesów i wątków procesy i wątki asynchroniczne – aktywowane przerwaniami procesy i wątki synchroniczne – aktywowane układami odmierzania czasu procesy i wątki drugoplanowe – aktywowane gdy procesor ma wolne zasoby
3
Zdarzenia są reprezentowane przez przerwania
RTS mają reagować na zdarzenia (w restrykcyjnym czasie!) Zdarzenia są reprezentowane przez przerwania Przerwanie inicjuje ISR – procedurę obsługi przerwania i dodatkowo może się odbyć: odblokowanie wątku odblokowanie procesu Procesy i wątki asynchroniczne pozostają w stanie zablokowania wznawiane przez przerwania (zdarzenia systemowe) po wykonaniu wracają do stanu zablokowania
4
W czasie ISR inne przerwania są zablokowane
ISR wykonuje proste czynności, które nie podlegają szeregowaniu W czasie ISR inne przerwania są zablokowane Następnie kod obsługi przerwania może przekazać działanie procesowi lub wątkowi Zwykle wątki (bo mają krótszy czas wznowienia) są utworzone dla przerwań i czekają gotowe na przerwanie Wystąpienie przerwania inicjuje: obsługę ISR aktywację wątku dla tego przerwania przejście wątku w stan oczekiwania
5
wątek obsługi przerwania
ISR W2 odblokowanie wątku W2 przerwanie blokada wątek obsługi przerwania proces1 wątek proces3 wątek wątek proces4 wątek proces2 wątek wątek wątek wątek wątek wątek wątek wątek .. do problematyki wątków jeszcze wrócimy….
6
…podsumowując, mogą być 3 sytuacje:
ISR wykona proste czynności ISR wykona proste czynności, resztę zleci procesowi lub wątkowi ISR od razu zleci czynności procesowi lub wątkowi
7
Inicjacja RTS Trudność studiowania długich instrukcji, aby poznać docelową platformę. Analizowanie tabel pamięci, rejestrów i diagramów przedstawiających wewnętrzną strukturę sprzętową. Problemy: - jakie sposoby załadowania obrazu systemu podział obszarów pamięci, w których poszczególne części systemu powinny się znaleźć jakie metody inicjalizacji aplikacji w jaki sposób pobierane będą dane wejściowe i generowane sygnały wyjściowe.
8
Po uruchomieniu urządzenia, przejmuje nad nim kontrolę tzw
Po uruchomieniu urządzenia, przejmuje nad nim kontrolę tzw. boot image (również obecny w ROM) oraz inicjalizuje sprzęt. Kiedy pamięć oraz podstawowe urządzenia są już zainicjalizowane, zaczyna wykonywać się loader - IPL, czyli właściwy program ładujący, który znajduje się na docelowym urządzeniu - zwykle w pamięci ROM - i służy do pobrania z komputera hosta obrazu systemu - współdziała z oprogramowaniem hosta. Obraz może też być w ROM. Używa się łącza szeregowego, chociaż programy ładujące potrafią korzystać z połączeń sieciowych oraz dokonywać operacji na pamięci flash.
9
Loader pobiera obraz bezpośrednio do pamięci RAM
Loader pobiera obraz bezpośrednio do pamięci RAM. Musi rozumieć format przesyłanego pliku - zawarte są w nim instrukcje określające pod jakimi adresami oraz w jakich częściach pamięci należy umieścić określone sekcje. Po zakończeniu transmisji, program ładujący przekazuje kontrolę do zainstalowanego obrazu.
10
Po uruchomieniu urządzenia, jego procesor zaczyna pobierać kolejne instrukcje z określonego systemowego obszaru pamięci. Znajduje się tam tzw. wektor resetujący, który ze względu na swoje ograniczone rozmiary, zawiera tylko instrukcję skoku do miejsca zawierającego właściwy kod inicjalizujący.
12
Zaraz po uruchomieniu urządzenia, rejestry jego procesora przyjmują wartości domyślne.
Następnie, program ładujący: wyłącza procedury obsługi przerwań, inicjalizuje pamięć RAM, inicjalizuje pamięci podręczne procesora dokonuje bardzo podstawowego sprawdzenia sprzętu. Przyczyną wyłączenia obsługi przerwań jest brak gotowości systemu do ich obsługi. Pamięć RAM jest o wiele szybsza niż ROM, czy flash oraz dodatkowo umożliwia prostsze wykonanie operacji zapisu, dlatego też program ładujący kopiuje całość lub tylko część obrazu systemu do pamięci RAM. Później, następuje uruchomienie sprzętu, jak np. urządzenia wejścia - wyjścia oraz sterowanie przejmuje właściwy system operacyjny.
13
Obraz, który jest ładowany do maszyny docelowej, to zbiór wielu pakietów oprogramowania.
Są to między innymi: moduły odpowiedzialne za obsługę płyty, liczne sterowniki, system czasu rzeczywistego, który dostarcza podstawowe usługi i umożliwia operacje wejścia - wyjścia
14
Board Support Packages
15
Wszystkie te komponenty, są odpowiedzialne za pełną inicjalizację urządzenia.
inicjalizacja sprzętu, instalacja procedur obsługi przerwań i wyjątków, inicjalizacja samego systemu czasu rzeczywistego oraz poszczególnych jego aplikacji. Najbliżej sprzętu jest zbiór sterowników dla płyty głównej (BSP - board support packages – pakiety wspomagania płyty) - zazwyczaj są one pisane w języku niskiego poziomu oraz związane są z konkretną architekturą!
16
Pozostałe moduły implementowane w językach wysokiego poziomu - jak np
Pozostałe moduły implementowane w językach wysokiego poziomu - jak np. C. Uruchomienie samego systemu czasu rzeczywistego: inicjalizację jego obiektów i usług, jak np. procesy i wątki, kolejki, semafory, stworzenie stosu pamięci, obsługa komunikacji. Gdy zostanie uruchomiony moduł szeregujący procesy –(scheduler), użytkownik może uruchamiać wszelkie inne obecne w pamięci aplikacje. Wówczas system ma możliwość podziału dostępu do procesora oraz przekazywanie aplikacjom sterowania.
17
Hardware Database SDP info
Hardware Database SDP info Advantech AIMB Intel® Core™ i7/i5/i3/Pentium® processor with Q57 chipset Advantech AIMB Intel® Core™ i7 and i5 mobile processor with Intel QM57 chipset Advantech PCM Embedded Intel® Atom™ processor N450 Single Core/D510 Dual Core 1.66 GHz + ICH8M Advantech SOM x Intel Atom Z5xx & System Controller Hub US15W with Fastboot IPL and BIOS Concurrent Technologies Specifications Intel Crown Beach CRB Intel Atom & System Controller Hub US15W Intel EP80579 aka "Tolopai" Intel EP80579 SOC Kontron nanoETXexpress-SP 6.4.x Intel Atom Z5xx & System Controller Hub US15W with Fastboot IPL and BIOS MEN Intel Atom SP3 Intel Atom MEN Mikro Electronik Commercial Men Mikro Elektronik x86 BIOS SP2, 6.3.2, 6.4.x x86 Dell PowerEdge 840 BASE Desktop/Server x86 Dell Lattitude D820 Laptop SP3, x86 Dell Lattitude D830 Laptop , 6.4.x x86 …i wiele innych
18
Rozruch systemu QNX – podsumowanie
Procesor wykonuje kod zapisany w BIOS'ie (albo ROM monitorze) BIOS przekazuje sterowanie do loadera - IPL. Tutaj ładowany jest do pamięci program startup Uruchamiany jest startup, ładowana jest pozostała część obrazu (OS boot image) Sterowanie przekazywane jest do procnto. Ten wykonuje skrypty startowe i kontynuuje pracę.
19
QNX Momentics IDE Ułatwia szybkie tworzenie aplikacji RTS
Integrated Developement Environment zintegrowane środowisko programistyczne Ułatwia szybkie tworzenie aplikacji RTS RAD – rapid application development Testowanie systemu: host aplikacji – wykonanie na QNX – target - cel
20
Kolejność czynności: Uruchomienie agenta qconn w VMPlayer
Nowy QNX/C projekt – built variant x86 Kompilacja – (Built project) Ustawienie celu (target) – komunikacja z maszyną wirtualną, gdzie mamy QNX – Run configurations… Wykonanie – Run ze środowiska IDE – target - IP maszyny wirtualnej bezpośrednio z QNX – po udostępnieniu binariów programu z wykorzystaniem IP wirtualnej karty sieciowej VMNet (proces fs-cifs) Obserwacja działającego systemu – perspektywa QNX
22
Argumenty procesu głównego
int main(int argc, char *argv[]) { printf("Pierwszy proces\n"); printf("Arg0:%s\n",argv[0]); printf("Arg1:%s\n",argv[1]); …. Pierwszy proces Arg0:execl1ja Arg1:abc
23
Pliki nagłówkowe #include <stdlib.h> #include <stdio.h>
i inne #include <sched.h> #include <pthread.h> wykorzystamy niebawem
24
PID – identyfikator procesu
Każdy proces ma swój PID – identyfikator. Możemy go wyświetlić korzystając z funkcji: int getpid() Procesy tworzą hierarchię zależności, każdy proces ma swojego rodzica (za wyjątkiem procesu systemowego procnto o identyfikatorze 1). Identyfikator rodzica można uzyskać za pomocą funkcji: int getppid() w systemie QNX polecenie: ps -A
25
printf("Proces macierzysty: %u\n", pid);
Przykład …. int pid= getpid(); int ppid= getppid(); printf("Proces macierzysty: %u\n", pid); printf("Proces rodzic: %u\n", ppid);
26
Tworzenie kopii procesu macierzystego
int pid=fork() Proces potomny w momencie utworzenia posiada: własny segment kodu, własny segment danych i stosu. Wartości zmiennych w procesie potomnym są takie same jak w procesie macierzystym przed wykonaniem funkcji fork, lecz potem oba procesy mogą dokonywać ich zmiany . Funkcja zwraca: 0 - w kodzie procesu potomnego PID nowego procesu - w procesie macierzystym -1 gdy nowy proces nie może być utworzony
27
Przykład stworzenie kopii procesu potomny macierzysty int x=10;
printf("x=%u\n", x); int pm = getpid(); printf("Proces macierzysty: %u\n", pm); int pp = fork(); printf("---%u---%u---\n",getpid(), getppid()); if (pp==0) { printf("To pisze potomny:"); x++; printf("---%u---%u---%u\n",getpid(), getppid(),x); sleep(2); } else { printf("To pisze macierzysty:"); x--; stworzenie kopii procesu potomny macierzysty x=10 Proces macierzysty: To pisze potomny: To pisze macierzysty:
28
int i,status; int x=10; printf("Proces MAIN start id====%u, x pocz=%u \n",getpid(),x); for (i=1;i<=2;i++) { printf("i: %u\n",i); int pp=fork(); if (pp==0) { x--; printf("Proces potomny odejmuje 1- id: %u id_ojca: %u, x=%u \n",getpid(),getppid(),x); } else { x+=4; printf("Proces macierzysty dodaje 4 - id: %u id_ojca: %u, x=%u\n",getpid(),getppid(),x); printf("OBYDWA: i: %u, x= %u\n",i,x); Proces MAIN start id==== , x pocz=10 i: 1 Proces potomny odejmuje 1 - id: id_ojca: , x=9 Proces macierzysty dodaje 4 - id: id_ojca: , x=14 OBYDWA: i: 1, x= 9 OBYDWA: i: 1, x= 14 i: 2 Proces macierzysty dodaje 4 - id: id_ojca: , x=18 Proces macierzysty dodaje 4 - id: id_ojca: , x=13 Proces potomny odejmuje 1 - id: id_ojca: , x=13 Proces potomny odejmuje 1 - id: id_ojca: , x=8 OBYDWA: i: 2, x= 18 OBYDWA: i: 2, x= 13 OBYDWA: i: 2, x= 8 Proces MAIN start id==== , x pocz=10 i: 1 Proces potomny odejmuje 1 - id: id_ojca: , x=9 Proces macierzysty dodaje 4 - id: id_ojca: , x=14 OBYDWA: i: 1, x= 9 OBYDWA: i: 1, x= 14 i: 2 Proces macierzysty dodaje 4 - id: id_ojca: , x=18 Proces macierzysty dodaje 4 - id: id_ojca: , x=13 Proces potomny odejmuje 1 - id: id_ojca: , x=13 Proces potomny odejmuje 1 - id: id_ojca: , x=8 OBYDWA: i: 2, x= 18 OBYDWA: i: 2, x= 13 OBYDWA: i: 2, x= 8 18 14 14 2 13 1 9 13 13 2 8
29
ważne priorytety i szeregowanie
czyli 4 procesy … ale czasem jest tak! Proces MAIN start id==== , x pocz=10 i: 1 Proces macierzysty dodaje 4 - id: id_ojca: , x=14 Proces potomny odejmuje 1 - id: id_ojca: , x=9 OBYDWA: i: 1, x= 14 OBYDWA: i: 1, x= 9 i: 2 Proces potomny odejmuje 1 - id: id_ojca: , x=13 Proces macierzysty dodaje 4 - id: id_ojca: , x=18 OBYDWA: i: 2, x= 13 OBYDWA: i: 2, x= 18 Proces macierzysty dodaje 4 - id: id_ojca: , x=13 Proces potomny odejmuje 1 - id: id_ojca: , x=8 OBYDWA: i: 2, x= 8 13 14 2 18 1 9 13 2 8 ważne priorytety i szeregowanie
30
WAIT Funkcja wait umożliwia synchronizację procesów.
W przypadku napotkania funkcji wait proces macierzysty oczekuje na zakończenie procesu potomnego (pierwszego, jeśli jest ich wiele) – wówczas dostępny jest status. Wcześniejsze zakończenie procesu macierzystego niż potomnego spowodowałoby, że potomny straciłby swojego przodka. Funkcja zwraca PID procesu potomnego. pid_t wait (int *status) Gdy status jest różny od NULL, stan procesu potomnego jest wskazywany przez zmienną status. Istnieją makro, jak np. WIFEXITED(status), umożliwiające odczytanie informacji ze zmiennej status: 1 – jeśli normalne zakończenie procesu 0 - jeśli błąd
31
pid=wait(&status); 18 14 14 wait 2 13 13 1 wait 9 2 8
int i,status,pid; int x=10; printf("Proces MAIN start id====%u, x pocz=%u \n",getpid(),x); for (i=1;i<=2;i++) { printf("i: %u\n",i); int pp=fork(); if (pp==0) { x--; printf("Proces potomny odejmuje 1- id: %u id_ojca: %u, x=%u \n",getpid(),getppid(),x); } else { x+=4; printf("Proces macierzysty dodaje 4 - id: %u id_ojca: %u, x=%u\n",getpid(),getppid(),x); pid=wait(&status); printf("OBYDWA: i: %u, x= %u\n",i,x); potomny macierzysty Proces MAIN start id==== , x pocz=10 i: 1 Proces macierzysty dodaje 4 - id: id_ojca: , x=14 Proces potomny odejmuje 1 - id: id_ojca: , x=9 OBYDWA: i: 1, x= 9 i: 2 Proces macierzysty dodaje 4 - id: id_ojca: , x=13 Proces potomny odejmuje 1 - id: id_ojca: , x=8 OBYDWA: i: 2, x= 8 OBYDWA: i: 2, x= 13 OBYDWA: i: 1, x= 14 Proces macierzysty dodaje 4 - id: id_ojca: , x=18 Proces potomny odejmuje 1 - id: id_ojca: , x=13 OBYDWA: i: 2, x= 18 18 14 14 wait 2 13 13 1 wait 9 2 8
32
pid=wait(&status); printf("pid %u status: %u\n",pid,WIFEXITED(status)); pid status: 1
33
execl(path/fname,arg0,arg1,...,NULL)
Przekształca bieżący proces w inny proces, którego kod wykonywalny zawarty jest w pliku fname, przekazuje mu parametry arg0, arg1,arg2, itd. execl(path/fname,arg0,arg1,...,NULL) czyli proces wywołujący jest zakończony
34
Projekt execl1 printf("Pierwszy proces\n"); int i; for (i=1;i<4;i++) { printf("i=%u\n",i); } execl("/mnt/tmp2/ex2/x86/o/execl2","execl2","10","20",NULL); printf("czy dziala?\n");// tego tekstu już nie będzie!!! return EXIT_SUCCESS; Projekt execl2 Pierwszy proces i=1 i=2 i=3 To drugi ile arg=3 x=execl2 x=10 x=20 aaa: No error printf("To drugi\n"); int x; printf("ile arg=%u\n",argc); for (x=0;x<argc;x++) { printf("x=%s\n",argv[x]); } perror("aaa"); return EXIT_SUCCESS;
35
Po udostępnieniu fs-cifs…
36
Tworzenie procesów współbieżnych
spawnl Funkcja spawnl używana jest do tworzenia nowych procesów, z możliwością wyboru trybu pracy procesu macierzystego, który może być zakończony, wykonywany współbieżnie lub z oczekiwaniem na zakończenie potomnego. pid_t spawnl(int mode, char * path, arg0,arg1,..., argN,NULL) mode - tryb wykonania procesu: P_WAIT, P_NOWAIT, P_OVERLAY, P_NOWAITO, path – ścieżka z nazwą pliku wykonywalnego, arg0 - argument 0 przekazywany do funkcji main tworzonego procesu. Powinna być to nazwa pliku wykonywalnego ale bez ścieżki, arg1, ...argN – argumenty przekazywane do funkcji main tworzonego procesu. Funkcja zwraca: PID (typ pid_t lub integer) utworzonego procesu -1 gdy wystąpi błąd. Tryby wykonania: P_WAIT - proces czeka na zakończenie procesu potomnego P_NOWAIT - proces potomny wykonywany jest współbieżnie P_OVERLAY - proces bieżący zastępowany jest przez proces potomny
37
for(i=1;i <= atoi(argv[1]);i++) { printf("Potomny krok: %d \n",i);
int pid,i,res,status,test; test=1234; char buf[10]; res = spawnl(P_WAIT,"/mnt/tmp2/spawnl2/x86/o/spawnl2","spawnl2","10",NULL); //res = spawnl(P_OVERLAY,"/mnt/tmp2/spawnl2/x86/o/spawnl2","spawnl2","10",NULL); // res = spawnl(P_NOWAIT,"/mnt/tmp2/spawnl2/x86/o/spawnl2","spawnl2","10",NULL); if(res < 0) { perror("SPAWN"); exit(0); } for(i=1;i < 10;i++) { printf("Macierzysty - krok %d \n",i); sleep(1); pid = wait(status); printf("Proces %d zakonczony, status %d\n",pid,status); Potomny krok: 1 Potomny krok: 2 Potomny krok: 3 Potomny krok: 4 Potomny krok: 5 Potomny krok: 6 Potomny krok: 7 Potomny krok: 8 Potomny krok: 9 Potomny krok: 10 Potomny test: 0 Macierzysty - krok 1 Macierzysty - krok 2 Macierzysty - krok 3 Macierzysty - krok 4 Macierzysty - krok 5 Macierzysty - krok 6 Macierzysty - krok 7 Macierzysty - krok 8 Macierzysty - krok 9 Proces -1 zakonczony, status 0 int id, i,status,test ; for(i=1;i <= atoi(argv[1]);i++) { printf("Potomny krok: %d \n",i); sleep(1); } printf("Potomny test: %d \n",test); exit(i);
38
Priorytet procesu Jednym z atrybutów procesu jest jego priorytet.
Priorytet można uzyskać za pomocą funkcji: getprio() lub sched_getparam() a ustawić funkcjami: setprio() lub sched_setparam() Składnia funkcji getprio i setprio: int getprio(pid_t pid) – pobranie priorytetu procesu, gdy argument pid=0 funkcja zwraca priorytet procesu macierzystego int setprio(pid_t pid, int prio) – ustawienie priorytetu procesu - funkcja zwraca poprzedni priorytet lub -1 gdy wystąpi błąd.
39
printf("Prio macierzysty:%u\n",getprio(0));
setprio(0,37); printf("Prio macierzysty:%u\n",getprio(0)); spawnl(P_NOWAIT,"/mnt/tmp/spawnl2/x86/o/spawnl2","spawnl2","10",NULL); for(i=1;i <= 10;i++) { printf("Macierzysty - krok %d \n",i); sleep(1); } współbieżne setprio(getpid(),3); printf("Prio potomny:%u\n",getprio(getpid())); for(i=1;i <= atoi(argv[1]);i++) { printf("Potomny krok i=: %d \n",i); sleep(1); } Prio macierzysty:37 Macierzysty - krok 1 Prio pot:3 Potomny krok i=: 1 Macierzysty - krok 2 Potomny krok i=: 2 Macierzysty - krok 3 Potomny krok i=: 3 Macierzysty - krok 4 Potomny krok i=: 4 Prio macierzysty:3 Macierzysty - krok 1 Prio pot:38 Potomny krok i=: 1 Potomny krok i=: 2 Macierzysty - krok 2 Potomny krok i=: 3 Macierzysty - krok 3 Potomny krok i=: 4 Macierzysty - krok 4
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.