Buforowanie, spooling i przechowywanie podręczne

Buforowanie


Ogólnym celem buforowania jest niwelowanie różnic, co oddaje angielskie znaczenie tego terminu (ang. buffer = zderzak). Niwelowanie różnic polega na wykorzystaniu szybkiej pamięci operacyjnej do gromadzenia danych, zanim zostaną one przekazane do urządzenia.

Różnice mogą dotyczyć szybkości pracy urządzeń. Typowy przypadek dotyczy szybkiego producenta, przekazującego dane, z których przetwarzaniem nie nadąża odbiorca — konsument. Czasami, w celu równoważenia obciążenia urządzenia szybsze otrzymują więcej pracy do wykonania, w związku z czym nie mogę natychmiast reagować na żądania urządzeń powolnych. Wówczas również przydaje się buforowanie.

Inny przypadek dotyczy efektywności transmisji danych pomiędzy urządzeniami blokowymi. Bloki przekazywane przez jedno urządzenie mogą mieć innych rozmiar, niż bloki akceptowane przez inne urządzenie. W celu uniknięcia zbędnych operacji wejścia-wyjścia dane gromadzi się w buforze w celu „uformowania” jednostki o właściwym rozmiarze.

Nieco odmiennym przypadkiem jest semantyka kopii. Przypadek ten wiąże się z synchronizacją współbieżnego dostępu, a dokładniej koniecznością uniknięcia długotrwałego blokowania dostępu do danych. W tym celu robi się kopie danych w pamięci, które następnie można przekazać do urządzenia, podczas gdy proces może operować na danych oryginalnych.

Dopasowanie różnic szybkości


Przykładem dopasowania szybkiego producenta do stosunkowo małej przepustowości konsumenta jest drukowanie. Drukarka jest urządzeniem powolnym, podczas gdy komputer potrafi przygotować dane do wydruku dość szybko, nawet w przypadku dokumentu ze skomplikowanym formatowaniem, rysunkami itp. Strumień, który ma być przekazany do drukarki jest więc gromadzony w pamięci, co umożliwia po stosunkowo krótkim czasie kontynuacje pracy z drukowanym właśnie dokumentem.

W obsłudze drukarki stosowany jest dodatkowo tzw. spooler, co zostanie omówione z dalszej części.

Dopasowanie jednostek transmisji


Przykładem dopasowania jednostek transmisji jest zapis na dysku danych odbieranych z sieci. Po wyodrębnieniu z ramki sieciowej danych aplikacyjnych może się okazać, że ich objętość jest mniejsza niż rozmiar sektora. Dane można oczywiście zapisać, tzn. zapisać sektor dysku, przy czym część sektora będzie zwierać wartości przypadkowe lub 0. Po otrzymaniu kolejnej ramki dane w sektorze można uzupełnić, ale operacja taka wymaga wczytania sektora do pamięci — do bufora, uzupełnienia świeżo otrzymanymi danymi i ponownego zapisu. Buforowanie zatem i tak jest niezbędne na potrzeby realizacji operacji dyskowych. Tym nie mniej, lepiej przetrzymać niepełną zawartość bufora w pamięci i poczekać na uzupełnienie danymi z następnej ramki. W tym przypadku mamy do czynienia ze składaniem. Przy transmisji danych z dysku przez sieć w opisanej sytuacji może być z kolei potrzeba fragmentowania danych, czyli dzielenia w buforze na mniejsze części, dopasowane do pojemności ramki.

Semantyka kopii


Przykładem buforowania w celu zagwarantowania semantyki kopii jest zapis na dysku pliku, który podlega modyfikacji. Przypadek taki ma często miejsce, kiedy chcemy zachować bieżący stan dokumentu na wypadek awarii lub przed jakąś poważną modyfikacją, której może się nie udać wycofać. Transfer danych bezpośrednio z przestrzeni procesu oznacza ryzyko zapisania danych niespójnych. Ryzyko niespójności w tym przypadku polega na tym, że w trakcie realizacji operacji zapisu (wyjścia) plik w pamięci jest modyfikowany i część zapisanych zmian dotyczy zawartości sprzed modyfikacji, a część po modyfikacji. Można w ten sposób zapisać na dysku drugą połowę wprowadzanego właśnie zdania, pomimo że zlecenie zapisu zostało wydane przed rozpoczęciem wprowadzania tego zdania.

Można by oczywiście zablokować dostęp do obszaru pamięci z bieżącą zawartością pliku, ale zmusza to użytkownika do przerwania pracy na czas zapisu na dysku. Można zatem wykonać znacznie szybszą operację skopiowania odpowiedniego obszaru pamięci do bufora w jądrze, gdzie będzie gwarancja niezmienności danych.

slajd 38

Realizacja buforowania


Buforowanie można zrealizować na kilka sposobów, w zależności od zastosowania i intensywności korzystania z buforów. Całkowita rezygnacja z buforowania oznacza konieczność utrzymania urządzeń wyjściowych w gotowości do natychmiastowego działania lub blokowania pracy urządzeń wejściowych. Można zastosować bufor pojedynczy, który ma jednak pewne ograniczenie — albo jest w danej chwili czytany, albo zapisywany. W celu umożliwienia jednoczesnej pracy obu komunikującym się urządzeniom konieczne jest użycie co najmniej bufor podwójnego. Jedna z dwóch pozycji bufora jest w danej chwili zapisywana, a druga odczytywana, po czym następuje zmiana. W przypadku dużych tymczasowych rozbieżności w szybkości pracy urządzeń konieczny może być bufor cykliczny, w którym jest kilka pozycji. Producent zapełnia kolejne pozycje, a gdy dojdzie do końca, rozpoczyna ponownie od początku. Podobnie konsument pobiera dane z poszczególnych pozycji. Warunkiem poprawności takiego buforowania jest blokada producenta przed nadpisaniem pozycji, której konsument jeszcze nie odczytał oraz blokowanie konsumenta przed odczytaniem pozycji, której producent jeszcze nie zapisał (wielokrotnym odczytaniem tej samej pozycji). Tego typu problem rozważany będzie w module dotyczącym synchronizacji procesów.

slajd 39

Przechowywanie podręczne


Przechowywanie podręczne jest pewną formą buforowania (raczej utrzymywania danych w pamięci), której celem jest poprawa efektywności realizacji operacji wejścia-wyjścia poprzez udostępnianie danych w pamięci zamiast wykonywania operacji na urządzeniu.

W przypadku zlecenia odczytu danych z urządzenia są one przekazywane procesowi z bufora w pamięci podręcznej, z pominięciem operacji wejścia. Wymaga to utrzymania aktualnych danych w buforze pamięci podręcznej, a więc w wyniku operacji zapisu na urządzeniu musi nastąpić stosowana zmiana zawartości tego bufora. Operacja wyjścia może się ograniczyć do modyfikacji zawartości bufora. Właściwa operacja wyjścia na urządzeniu może nastąpić później i uwzględnić kilka zleceń zapisu ze strony procesów aplikacyjnych.

Tego typu technika stosowana jest powszechnie w obsłudze systemu plików, co będzie omawiane w następnych modułach. Jest ona również stosowana w obsłudze pamięci wirtualnej, ale w tym przypadku odnosi się do zawartość pamięci, urządzenie wymiany jest zatem wtórnym miejscem gromadzenia danych.

Spooling


Spooling jest akronimem od angielskiego określenia sequential peripheral operation on line , co można przetłumaczyć, oddając sens sformułowania, jako na bieżąco realizowana operacja sekwencyjna na urządzeniu wejścia-wyjścia.

Operacja sekwencyjna jest tutaj rozumiana jako operacja na urządzeniu o dostępie wyłącznym. Następna operacja może się rozpocząć dopiero po zakończeniu poprzedniej. Konieczne jest więc zagwarantowanie ciągłości strumienia danych, przekazywanych do urządzenia w ramach operacji wyjścia. Strumień taki nie może się przeplatać z innym strumieniem. Typowym przykładem urządzenia, obsługiwanego z wykorzystaniem techniki spoolingu, jest drukarka. Przeplatanie strumieni w przypadku takiego urządzenia oznacza wydruk, który może być zupełnie nieczytelny (pomieszanie linii, słów, znaków lub zupełna abstrakcja w przypadku grafiki).

Spooling polega więc na buforowaniu strumienia danych, przekazywanych do urządzenia dostępnego w trybie wyłącznym i rozpoczęciu operacji dopiero po zapamiętaniu całego strumienia. Ze względu na objętość strumienia buforowanie takie odbywa się najczęściej na dysku (tzw. spooler). Przekazywanie danych ze spoolera do urządzenia realizuje jeden proces lub wątek, co zapewnia sekwencyjność tej operacji.

Alternatywą dla spoolingu byłoby blokowanie urządzenia, tzn. jawny przydział urządzenia żądającemu procesowi i blokowanie dostępu innym procesom do czasu zwalniania. Takie rozwiązanie stwarza jednak problem uzależnienie zajętości urządzenia od „kaprysu” procesu. Jeśli proces przekaże tylko część strumienia, a drukowanie reszty będzie musiał odłożyć w czasie, drukarka pozostanie cały czas zajęta. W przypadku spoolingu drukowanie nie rozpocznie się, dopóki cały strumień nie zostanie zbuforowany, dzięki czemu przedłużające się przekazywanie danych nie blokuje innych procesów w dostępie do drukarki.