Deskryptory dużych systemów Burroughsa

Deskryptory są cechą architektoniczną dużych systemów Burroughs , w tym obecnych (od 2006 r.) systemów Unisys Clearpath / MCP. Oprócz tego, że są oparte na stosie i znacznikach , godną uwagi cechą architektoniczną tych systemów jest to, że są one oparte na deskryptorach. Deskryptory to sposób na posiadanie danych , które nie znajdują się na stosie, jak w przypadku tablic i obiektów . Deskryptory są również używane do łańcuchowych , jak w kompilatorach i aplikacjach komercyjnych .

Detale

Deskryptory opisują obszary pamięci, żądania we/wy i wyniki we/wy. Zawierają pola wskazujące np. rodzaj deskryptora, adres, długość, czy dane znajdują się w pamięci. Szczegóły różnią się w zależności od linii produktów i rodzaju deskryptora. Poniższy tekst numeruje skrajny lewy (najbardziej znaczący) bit jako 0, zgodnie z dokumentacją Burroughsa.

Deskryptory programu i danych mają bit zwany „bitem obecności” lub „bitem p”; wskazuje, czy obiekt, do którego odnosi się deskryptor, znajduje się obecnie w pamięci, czy w pamięci dodatkowej. Ten bit jest używany do implementacji pamięci wirtualnej .

Pamięć wirtualna została pierwotnie opracowana na potrzeby projektu Atlas na Uniwersytecie w Manchesterze pod koniec lat pięćdziesiątych. Pragnąc zobaczyć to w zastosowaniach komercyjnych, zaprosili inżynierów z kilku firm komputerowych na seminarium, w tym z Burroughs i IBM . [ potrzebne źródło ] Model B5000, wprowadzony na rynek w 1961 roku, był pierwszym komercyjnym komputerem wyposażonym w pamięć wirtualną. W połowie lat sześćdziesiątych inni dostawcy, w tym IBM, RCA i General Electric , opracowali maszyny obsługujące pamięć wirtualną z systemami operacyjnymi zorientowanymi na podział czasu; IBM nie obsługiwał pamięci wirtualnej w maszynach przeznaczonych do ogólnego przetwarzania danych do 1972 roku.

Gdy odwołuje się do deskryptora, sprzęt sprawdza bit p. Jeśli wynosi 1, dane znajdują się w pamięci w miejscu wskazanym w polu adresowym. Jeśli p-bit wynosi 0, blok danych nie jest obecny i zgłaszane jest przerwanie ( przerwanie p-bitowe ) oraz wprowadzany jest kod MCP , aby blok był obecny. W tym przypadku, jeśli pole adresowe ma wartość 0, blok danych nie został przydzielony (init p-bit) i MCP szuka wolnego bloku, którego rozmiar jest podany w polu długości.

Ostatni scenariusz p-bitowy ma miejsce, gdy p-bit wynosi 0, co wskazuje, że dane nie znajdują się w pamięci, ale adres jest różny od zera, co wskazuje, że dane zostały przydzielone i w tym przypadku adres reprezentuje adres dysku w obszar pamięci wirtualnej na dysku. W tym przypadku zgłaszane jest przerwanie typu p-bit i jest ono odnotowywane jako „inny” bit p.

B5000, B5500 i B5700

B5000 był pierwszym komputerem opartym na deskryptorach. Każdy deskryptor ma flagę (bit 0) równą 1. Deskryptory danych zawierają 15-bitowy adres pamięci i 10-bitowy rozmiar, podobnie jak większość deskryptorów we/wy. Deskryptory programu i deskryptory wyników zewnętrznych mają 15-bitowy adres, ale nie mają pola rozmiaru.

B5x00 Deskryptory programu

Deskryptory programów służą do definiowania segmentów programów. Albo wywołanie operandu, albo wywołanie deskryptora, które odnosi się do deskryptora programu, spowoduje wywołanie podprogramu standardowego, jeśli bit obecności wynosi 1, w przeciwnym razie spowoduje przerwanie obecności.

B5x00 Deskryptory programu
0 1 2 3 4 5 6 7 8-17 18-32 33-47
Flaga I Obecność I Tryb A Adres
1 1
0=brak w pamięci 1=w pamięci
1
0=słowo 1=znak

0=argument niewymagany 1=argument wymagany

Deskryptory danych

Deskryptory danych odnoszą się albo do bloku danych obecnych w pamięci (P=1) albo do bloku danych, który musi zostać wczytany do pamięci (P=0), w zależności od wartości bitu obecności. Zarówno wywołanie argumentu, jak i wywołanie deskryptora, które odnosi się do deskryptora danych, sprawdzi bit obecności i pole rozmiaru; jeśli bit obecności wynosi 0, nastąpi przerwanie obecności; jeśli pole rozmiaru jest niezerowe, to drugie słowo na stosie musi znajdować się w zakresie, w przeciwnym razie nastąpi przerwanie indeksu.

B5x00 Deskryptory danych
0 1 2 3-7 8-17 18 19 20 21-32 33-47
Flaga I Obecność Rozmiar I C Adres
1 0
0=brak w pamięci 1=w pamięci

Zarezerwowane dla MPK

Zarezerwowane dla MPK

0=zmiennoprzecinkowe 1=liczba całkowita

Zarezerwowane dla MPK

Deskryptory wejść/wyjść

Deskryptory wejść/wyjść B5x00
0 1 2 3-7 8-17 18-32 33-47
Flaga I
Alternatywny zewnętrzny
Jednostka Rozmiar Zależne od urządzenia
Adres
1 1
0=zapis 1=odczyt

Zewnętrzne deskryptory wyników

Zewnętrzny deskryptor wyników zawiera deskryptor we/wy używany do inicjowania operacji z zastąpionymi niektórymi polami.

B5x00 Zewnętrzne deskryptory wyników
0 1 2 3-7 8-25 26-32 33-47
Flaga I
Alternatywny zewnętrzny
Jednostka Nieistotny Zależne od urządzenia
Adres
1 1
0=zapis 1=odczyt
warunki błędu

ostatnia lokalizacja

B6500, B7500 i następcy

Deskryptory opisują bloki danych. Każdy deskryptor zawiera 20- bitowe pole adresowe odnoszące się do bloku danych. Każdy blok ma długość, która jest przechowywana w deskryptorze, również 20 bitów. Podano również rozmiar danych, przy czym są to 4-, 6-, 8- lub 48-bitowe dane w polu trzybitowym.

Pierwszym komputerem z tą architekturą był B6500. w tej implementacji znaczenie różnych bitów stanu było następujące:

  • Bit 47 – Bit obecności (bit P)
  • Bit 46 – Bit kopiowania
  • Bit 45 – Indeksowany bit
  • Bit 44 – Bit podzielony na segmenty
  • Bit 43 – Bit tylko do odczytu

W późniejszych implementacjach te bity stanu ewoluowały, aby nadążyć za rosnącymi rozmiarami pamięci i uzyskanymi wglądami.

Użycie w kompilatorach

W ALGOL granice tablicy są całkowicie dynamiczne, można je pobrać z wartości obliczonych w czasie wykonywania, w przeciwieństwie do Pascala , gdzie rozmiar tablic jest ustalany w czasie kompilacji. Jest to główna słabość Pascala zdefiniowana w jego standardzie, ale została usunięta w wielu komercyjnych implementacjach Pascala, zwłaszcza w implementacjach Burroughs (zarówno wersja University of Tasmania autorstwa Arthura Sale'a i Roya Freaka, jak i implementacja w Burroughs Slice autorstwa Matta Millera i in.)

W programie w środowisku Burroughs tablica nie jest przydzielana, gdy jest deklarowana, ale tylko wtedy, gdy jest dotykana po raz pierwszy - w ten sposób można zadeklarować tablice i uniknąć narzutu związanego z ich przydzielaniem, jeśli nie są używane.

nie są potrzebne wywołania systemu alokacji pamięci niskiego poziomu, takie jak wywołania klasy malloc w C i Unix - tablice są przydzielane automatycznie w miarę ich używania. Oszczędza to programiście wielkiego ciężaru wypełniania programów podatną na błędy czynnością zarządzania pamięcią, co ma kluczowe znaczenie w aplikacjach mainframe .

Podczas przenoszenia programów w językach niższego poziomu, takich jak C, struktura pamięci C jest rozwiązywana przez samodzielną alokację pamięci w ramach dużego przydzielonego bloku B5000 - w ten sposób bezpieczeństwo reszty systemu B5000 nie może zostać naruszone przez błędne programy C. W rzeczywistości wiele przepełnień bufora w pozornie poprawnie działających programach C zostało wykrytych po przeniesieniu do architektury B5000 [ potrzebne źródło ] . C, podobnie jak Pascal, został również zaimplementowany przy użyciu systemu kompilatora Slice (który, podobnie jak LLVM , wykorzystuje wspólny generator kodu i optymalizator dla wszystkich języków). Kompilator C, system wykonawczy, POSIX , a także port wielu narzędzi uniksowych wykonał Steve Bartels. Kompilator Eiffla został również opracowany przy użyciu Slice.

W przypadku programów zorientowanych obiektowo, które wymagają bardziej dynamicznego tworzenia obiektów niż architektura B5000, obiekty najlepiej przydzielać w jednym bloku B5000. Taka alokacja obiektów jest na wyższym poziomie niż malloc w C i najlepiej jest zaimplementować ją za pomocą nowoczesnego, wydajnego modułu wyrzucania elementów bezużytecznych .

Integracja w architekturze pamięci

Pole adresu w B5000 ma tylko 15 bitów, co oznacza, że ​​deskryptory mogą adresować tylko 32 000 słów (192 KB) pamięci. B6500 rozszerzył to do 20 bitów lub słów 1 Meg (6 MB). W połowie lat siedemdziesiątych było to jeszcze znaczące ograniczenie architektury. Aby temu zaradzić, wdrożono dwa rozwiązania:

  1. Swapper – to rozwiązanie faktycznie implementuje kolejną warstwę poza zarządzaniem pamięcią, przenosząc jednocześnie duże klastry powiązanych danych do iz pamięci.
  2. ASN – to rozwiązanie pozwala na fizyczną konfigurację większej ilości pamięci w systemie, podzielonej na oddzielnie adresowalne bloki. Ta architektura stała się znana jako pamięć ASN (Address Space Number). Pamięć jest logicznie podzielona na dwa obszary, przydzielając niskie adresy pamięci do globalnej przestrzeni adresowej dla systemu operacyjnego i oprogramowania pomocniczego oraz wysokie adresy pamięci do kilku równoległych lokalnych przestrzeni adresowych dla poszczególnych programów. Przestrzenie adresowe są ponumerowane, zero oznacza globalną, 1..n oznacza lokalną przestrzeń adresową. Programy współdzielące dane są automatycznie umieszczane w tej samej przestrzeni adresowej.

Do wykorzystania tych funkcji nie były konieczne żadne modyfikacje kodu programu. Oba rozwiązania można nawet łączyć, ale ostatecznie wymagania dotyczące pamięci MCP i wymagania dotyczące udostępniania danych programu przerosły maksymalny rozmiar samych przestrzeni adresowych.

Wraz z pojawieniem się serii A na początku lat 80. znaczenie tego pola zostało zmienione, aby zawierało adres deskryptora głównego, co oznacza, że ​​można przydzielić 1-megabajtowe bloki danych, ale pamięć maszyny można znacznie rozszerzyć do gigabajtów a może terabajty. Ta architektura została nazwana pamięcią ASD (Advanced Segment Descriptors). Wymagało to nowej wspólnej specyfikacji mikrokodu, określanej jako Beta. Głównym wizjonerem pamięci ASD jest John McClintock. Później 3-bitowy znacznik pamięci został zwiększony do specyfikacji 4-bitowej, co pozwoliło na zwiększenie rozmiaru deskryptora segmentu z 20 do 23 bitów, umożliwiając jednoczesne adresowanie jeszcze większej ilości pamięci. Ta specyfikacja mikrokodu stała się znana jako poziom Gamma.

Zarządzanie pamięcią

Kolejna istotna zaleta została zrealizowana w przypadku pamięci wirtualnej. W projekcie B5000, jeśli blok danych został wprowadzony, wszystkie deskryptory odnoszące się do tego bloku musiały zostać znalezione, aby zaktualizować bit obecności i adres. W przypadku deskryptora głównego tylko bit obecności w deskryptorze głównym wymaga zmiany. MCP może również przenosić bloki w pamięci w celu zagęszczenia i musi jedynie zmienić adres w deskryptorze głównym.

Różnica między B5000 a większością innych systemów polega na tym, że inne systemy wykorzystywały głównie stronicowaną pamięć wirtualną, to znaczy strony są wymieniane w porcjach o stałym rozmiarze, niezależnie od struktury zawartych w nich informacji. Pamięć wirtualna B5000 działa z segmentami o różnej wielkości, zgodnie z opisem w deskryptorach.

Kiedy pamięć jest zapełniona do określonej pojemności, wywoływany jest proces systemu operacyjnego zwany „szeryfem zestawu roboczego”, aby albo skompaktować pamięć, albo rozpocząć przenoszenie segmentów z pamięci. Najpierw wybiera segmenty kodu, ponieważ nie można ich zmienić i można je ponownie załadować z oryginału w pliku kodu, więc nie trzeba ich zapisywać, a następnie segmenty danych, które są zapisywane do pliku pamięci wirtualnej.

Przerwania P-bitowe są również przydatne do mierzenia wydajności systemu. W przypadku alokacji po raz pierwszy „początkowe bity p” wskazują na potencjalny problem z wydajnością programu, na przykład, jeśli procedura alokacji tablicy jest ciągle wywoływana. Ponowne ładowanie bloków z pamięci wirtualnej na dysk może znacznie obniżyć wydajność systemu i nie jest to wina żadnego konkretnego zadania. Dlatego wiele dzisiejszych komputerów może zwiększyć wydajność systemu poprzez dodanie pamięci. Na maszynach B5000 „inne p-bity” wskazują na problem systemowy, który można rozwiązać, lepiej równoważąc obciążenie obliczeniowe w ciągu dnia lub dodając więcej pamięci.

W ten sposób architektura dużych systemów Burroughs pomaga optymalizować zarówno poszczególne zadania, jak i system jako całość.

Zabezpieczenie przed przepełnieniem bufora

Ostatnią i być może najważniejszą kwestią dotyczącą deskryptorów jest to, w jaki sposób wpływają one na komplementarne pojęcia bezpieczeństwa systemu i poprawności programu. Jednym z najlepszych narzędzi, jakie haker ma do skompromitowania dzisiejszych systemów operacyjnych, jest przepełnienie bufora. W szczególności C używa najbardziej prymitywnego i podatnego na błędy sposobu oznaczania końca łańcuchów, używając bajtu zerowego jako wskaźnika końca łańcucha w samym strumieniu danych.

Wskaźniki są implementowane w B5000 przez indeksowane deskryptory. Podczas operacji indeksowania wskaźniki są sprawdzane przy każdym przyroście, aby upewnić się, że ani blok źródłowy, ani docelowy nie są poza zakresem. Podczas operacji skanowania lub zastępowania mechanizmy używane do odczytu lub kopiowania dużych bloków pamięci, zarówno źródłowej, jak i docelowej, są sprawdzane przy każdym przyroście słowa pod kątem prawidłowego znacznika pamięci. Każdy segment pamięci jest ograniczony tagiem 3 słów, co spowodowałoby niepowodzenie takiej operacji. Każdy segment pamięci zawierający dane wrażliwe na integralność, takie jak kod programu, jest przechowywany w znaczniku 3 słów, co uniemożliwia niekontrolowany odczyt – nie mówiąc już o modyfikacji. W ten sposób istotne źródło błędów programu można wykryć wcześnie, zanim oprogramowanie trafi do produkcji, a bardziej znacząca klasa ataków na bezpieczeństwo systemu nie jest możliwa.

Notatki