Systemy wieloprocesorowe w oprogramowaniu krytycznym.

Written by Maciej Gajdzica

Senior Software Developer

Systemy safety-critical w ogromnej większości wykorzystują wiele procesorów. Zwykle systemy wieloprocesorowe kojarzą nam się ze zwiększeniem wydajności. Jednak w tym wypadku powody najczęściej są inne – najważniejsze z nich to:

  • zwiększenie bezpieczeństwa przez zastosowanie redundancji
  • uproszczenie developmentu poprzez wydzielenie skomplikowanych ale mniej krytycznych elementów do oddzielnych procesorów.

Zacznijmy od względów bezpieczeństwa. System musi zachować bezpieczeństwo również w przypadku uszkodzenia albo chwilowego błędu procesora. W przypadku dostatecznie poważnych awarii procesor może nie być w stanie samodzielnie wprowadzić systemu w stan bezpieczny. Dlatego niezbędna jest redundancja procesorów dająca drugiej jednostce obliczeniowej możliwość wykrycia problemu i podjęcia odpowiedniej akcji.

Najprostszym systemem redundantnym jest układ z procesorem nadzorującym. W takiej konfiguracji procesor główny implementuje wszystkie najważniejsze funkcje systemu. Rolą procesora nadzorującego jest jedynie monitorowanie pracy i interwencja w przypadku wykrycia jakiś poważnych anomalii.

Bardziej zaawansowanym rozwiązaniem jest zastosowanie dwóch niezależnych kanałów przetwarzania. Kanały te mają oddzielne wejścia i wyjścia, ale każde z nich może w razie potrzeby przełączyć system w stan bezpieczny. Kanały wymieniają się między sobą informacjami i dzięki temu potrafią łatwo zauważyć kiedy wartości na poszczególnych kanałach zbytnio się różnią. Pojedynczy kanał zwykle nie jest w stanie ocenić, czy różnica wynika z jego błędu, czy problem leży po drugiej stronie. Jednak nie ma to znaczenia – wykryto błąd, więc należy przejść w stan bezpieczny. System z dwoma niezależnymi kanałami może wykrywać o wiele bardziej złożone problemy niż system z procesorem nadzorującym.

Jeszcze bardziej zaawansowane rozwiązanie to system głosujący. W tym wypadku mamy do czynienia z jeszcze większą ilością niezależnych kanałów na przykład trzema, czy pięcioma (najlepiej jeśli liczba kanałów jest nieparzysta). System głosujący zbiera informacje ze wszystkich kanałów i na podstawie wybranej strategii określa sygnał wyjściowy. Oczywiście projektując musimy pamiętać również o zapewnieniu redundancji systemu głosującego, aby nie stał się single point of failure, czyli słabym punktem układu.

Systemy głosujące i z dwoma kanałami kontrolującymi się nawzajem mogą być łączone w rozwiązania hybrydowe. Możemy na przykład każdy kanał systemu głosującego złożyć z dwóch niezależnych kanałów. Możliwe też jest połączenie w drugą stronę – dwa niezależne kanały, gdzie każdy jest zrealizowany jako system głosujący.

Przy okazji implementacji systemów z wieloma kanałami realizującymi to samo zadanie ciekawym zagadnieniem jest diverse programming. To podejście, gdzie każdy z niezależnych kanałów jest realizowany przez oddzielny zespół programistów. Celem tego zabiegu jest zmniejszenie prawdopodobieństwa wystąpienia tego samego błędu w sofcie we wszystkich kanałach. Zespoły działają na podstawie tej samej dokumentacji, ale nie dzielą się kodem ani nawet pomysłami na implementację. Aby zwiększyć dywersyfikacje kanały mogą być realizowane na innych typach procesorów, w innych językach programowania albo korzystając z innych technik i metodologii.

Drugim powodem stosowania systemów wieloprocesorowych jest chęć wydzielenia części mniej krytycznej. Dzięki zastosowaniu w niej niższego poziomu bezpieczeństwa, a przez to mniej rygorystycznych norm – development może trwać dużo krócej. Dodatkowo możemy na przykład wykorzystać pewne gotowe rozwiązania, które nie spełniają standardy wyższych poziomów bezpieczeństwa.

Takie podejście jest szczególnie kuszące jeżeli chcemy wyposażyć nasz system w moduły takie jak stos TCP/IP, czy obsługa wyświetlacza graficznego. Takie moduły zwykle potrzebują dużo pamięci, często z dynamiczną alokacją i mogą zajmować dużo czasu procesora. Poza tym istnieje wtedy większa szansa błędu związanego z wyciekiem pamięci, przekroczeniem stosu, deadlockiem. Wydzielenie tych elementów do oddzielnych procesorów rozwiązuje nam wiele problemów.

Z punktu widzenia procesora realizującego krytyczne dla bezpieczeństwa funkcje, dodatkowe procesory mogą być przezroczyste. Procesor w torze sieciowym możemy potraktować jako element infrastruktury sieciowej. Jest to element tak zwanego czarnego kanału (black channel). Podobnie procesor obsługujący wyświetlanie danych na ekranie reaguje na pewne zdefiniowane komendy – można go więc potraktować jako część interfejsu HMI.

Wydzielając zadania do różnych procesorów możemy również uniknąć skomplikowanej integracji, kiedy nad tym samym kodem pracuje wiele osób. Integracje kodu z oddzielnych procesorów działających zgodnie ze ściśle zdefiniowanym interfejsem są dużo prostsze.

 

Maciej Gajdzica



Formularz kontaktowy