|
Obszar jest fragmentem pamięci wirtualnej. Jako taki, ma on wszystkie oczekiwane właściwości pamięci wirtualnej: ma on adres początkowy, rozmiar, adresy które zawiera są przylegające i mapowane do (prawdopodobnie nieciągłej) pamięci fizycznej. Cechy, które dostarcza obszar są takie, że ich nie dostaniesz używając "standardowej" pamięci:
- Obszary moga być współdzielone. Różne obszary mogą odnosić się do tej samej pamięci fizycznej. Patrząc w inny sposób, różne adresy pamięci wirtualnej mogą mapować do tych samych lokalizacji fizycznych. Ponadto, różne obszary nie muszą należeć do tej samej aplikacji. Przez tworzenie i "klonowanie" obszarów, aplikacje mogą łatwo współdzielić te same dane.
- Obszary mogą być blokowane w RAM. Możesz określić, że pamięć fizyczna obszaru jest zablokowana wewnątrz RAM kiedy jest on tworzony, zablokowany gdy strony są wymieniane, albo że będzie on wymieniany (na dysk do pliku wymiany lub z dysku z pliku) gdy jest potrzebny.
- Obszary mogą być chronione przed czytaniem i zapisem.
- Obszary są wyrównywane do strony. Obszary zawsze rozpoczynają się na granicy strony i są przydzielane w całkowitej wielokrotności rozmiaru strony. (strona ma 4096 bajtów, zgodnie z tym co reprezentuje stała B_PAGE_SIZE.)
- Możesz określić adres poczatkowy obszaru pamięci wirtualnej. Specyfikacja może wymagać, że obszar rozpoczyna się dokładnie na pewnym adresie, gdziekolwiek powyżej pewnego adresu, albo gdziekolwiek w ogóle.
Ponieważ obszary są wielkie - jedna strona, minimum - nie tworzysz ich dowolnie. Dwoma najbardziej nieodpartymi powodami do tworzenia obszaru są dwa pierwsze punkty opisane powyżej: by współdzielić dane pomiędzy różnymi aplikacjami i by zablokować pamięć wewnątrz RAM.
We wszystkich szczegółach traktujesz pamięć, którą daje Ci obszar dokładnie tak jak potraktowałbyś jakąkolwiek przydzieloną pamięć: Możesz czytać i zapisać ją przez manipulację wskaźnikiem albo przez standardowe funkcje takie jak memcpy() i strcpy(). Jedyną różnicą pomiędzy obszarami a pamięcią przydzieloną za pomocą funkcji malloc jest...
- Nigdy nie zwalniaj pamięci funkcją free() która przydziela obszar dla Ciebie. Jeżeli chcesz pozbyć się obszaru, zamiast niej użyj funkcji delete_area().
Każdy obszar, który tworzysz jest oznaczony liczbą area_id:
- Liczba area_id jest liczbą całkowitą dodatnią, która jest globalna i unikalna w granicach zakresu komputera. Nie są one unikalne poprzez sieć, ani nie są oni trwałe pomiędzy kolejnymi uruchomieniami.
- Liczby area_id są generowane i przypisywane automatycznie przez funkcje create_area() i clone_area(). Inne funkcje obszaru działają na tych liczbach area_id (są one wymagane jako argumenty).
- Chociaż są one globalne, liczby area_id mają małe znaczenie poza przestrzenią adresową (aplikacja), w której były one utworzene.
- Raz przypisana, liczba area_id nie zmienia się; ta liczba jest unieważniona kiedy wywołana funkcja delete_area() albo kiedy aplikacja (zespół), która ją utworzyła kończy działanie.
- Nie martwj się odzyskanymi liczbami area_id. Kiedy obszar jest usunięty, to jego area_id odchodzi raem z nim. (wartości area_id są odzyskiwane, ale obrót następuje przy 2^31.)
Obszary mogą też być (luźno) identyfikowane przez nazwy:
- Kiedy tworzysz obszar (przez create_area() lub clone_area()), uzyskujesz możliwość nazwania go.
- Nazwy obszaru nie są unikalne - duże liczby obszarów mogą być przypisane do tej samej nazwy.
- By odszukać obszar z nazwy, użyć funkcji FindArea().
Dla wielorakich aplikacji aby współdzielić wspólny obszar, jedna z aplikacji musi utworzyć obszar, a inne aplikacje klon obszaru. Klonujesz obszar przez wywołanie funkcji clone_area(). . Funkcja bierze, jako jej ostatni argument area_id obszaru źródłowego i zwraca nową (unikalną) liczbę area_id. Wszystkie dalsze odniesienia do sklonowanego obszaru (w aplikacji klonującej) muszą być oparte na area_id który jest zwrócony przez clone_area().Jak zatem aplikacja klonująca znajduje źródłowy area_id w pierwszym miejscu?
- Aplikacja źródłowa może przekazać "oryginalną" liczbę area_id do aplikacji klonującej.
- Aplikacja klonująca może znaleźć obszar z nazwy, przez wywołanie funkcji find_area().
Zauważ, że nazwy obszaru nie są muszą by być unikalne, więc metoda z funkcją find_area() jest w sobie trochę niepewności. Ale może ona być zminimalizowana przez zręczne utworzenie nazwy.
Pamięć fizyczna, która tkwi pod obszarem nigdy nie jest wprost kopiowana - na przykład, mechanizm obszaru nie wykonuje "kopii do zapisu". Jeżeli dwa obszary odnoszą się do tej samej pamięci z powodu klonowania, modyfikacja danych, która jest wprowadzona przez jeden obszar będzie widoczna w innym obszarze.
Kiedy pracujesz z umiarkowanie dużymi ilościami danych, co jest tak częstym przypadkiem, że wolałbyś, aby dane pozostały w RAM, nawet jeżeli reszta twojej aplikacji musi być wymieniona na dysk. Argument do wywołania funkcji create_area() pozwala Ci deklarować schemat blokujący, który pragniesz zastosować do swojego obszaru, przez użycie jednej z następujących stałych:
Stała Znaczenie B_FULL_LOCK Pamięć obszaru jest zablokowana wewnątrz RAM gdy obszar jest tworzony i nie będzie ona wymieniana na dysk. B_CONTIGUOUS Nie tylko jest zablokowana pamięć obszaru w RAM, jest też zagwarantowane aby był on przyległym. Jest szczególnie - a być może wyłącznie - użyteczne dla projektantów pewnych typów sterowników urządzeń. B_LAZY_LOCK Pozwala pojedynczym stronom pamięci aby były przeniesione do RAM w pierwotnej kolejności a następnie blokuje je. B_NO_LOCK Strony nigdy nie sa blokowane, są one wymieniane na dysk lub z dysku wtedy gdy są potrzebne. B_LOMEM Jest to specjalna stała, która jest używana dla obszarów, które potrzebują być zablokowane, przyległe i które leżą wewnątrz pierwszych 16MB pamięci fizycznej. Ludzie, którzy potrzebują tej stałej o co chodzi. Zauważ, że blokowanie obszaru zasadniczo zmniejsza ilość RAM, która może być używana przez inne aplikacje a zatem powiększa prawdopodobieństwo wymiany. Tak więc nie powinieneś blokować jej po prostu dlatego, że jesteś chciwy. Ale jeżeli obszar, który blokujesz ma być współdzielony poomiędzy kilka innych aplikacji, albo jeżeli piszesz aplikację czasu rzeczywistego, która przetwarza wielkie porcje danych, wtedy to nadużycie blokowania może dać się uzasadnić.
Schemat blokowania jest ustawiany przez funkcję create_area() i jest potem niezmienny. Nie możesz ponownie zadeklarować zamka kiedy klonujesz obszar.
Ostatecznie, używasz obszaru dla pamięci wirtualnej, którą on reprezentuje: Tworzysz obszar ponieważ chcesz trochę pamięci, do której możesz zapisać i z której możesz czytać dane. Te działania są wykonywane w zwykły sposób, przez odniesienia (referencje) do określonych adresów. Ustawianie wskaźnika na lokacji wewnątrz obszaru, i sprawdzanie, czy nie przekroczyłeś granic pamięci obszaru kiedy zwiększasz wskaźnik (podczas czytania albo zapisywania) jest realizowane na Twoją własną odpowiedzialność. Aby robić to właściwie, potrzebujesz znać adres początkowy obszaru i jego zasięg:
- Adres początkowy obszaru jest utrzymywany jako pole adresu address w jego strukturze area_info; odzyskujesz area_info dla pojedynczego obszaru poprzez funkcję get_area_info().
- Wielkość obszaru (w bajtach) jest dana jako pole rozmiaru size jego struktury area_info.
Ważnym punkt, co do area_info, jest to, że pole adresu address jest ważne tylko dla aplikacji, która tworzyła albo sklonowała obszar (innymi słowy, aplikacja, która utworzyła area_id, który z kolei był przekazany do get_area_info()). Chociaż pamięć, która leży pod obszarem jest globalna, adres, który dostajesz ze struktury area_info odnosi się do określonej przestrzeni adresowej.
Jeżeli jest tutaj jakieś pytanie czy określony area_id jest "miejscowy" albo "obcy," to możesz porównać pole area_info.team z zespołem twojego wątku.
Kiedy twoja aplikacja kończy działanie, obszary (liczby area_id) które to utworzyła przez create_area() lub clone_area() są automatycznie unieważniane. Pamięć leżąca pod obszarem, jednak, nie jest koniecznie zwalniana. Pamięć obszaru jest zwalniana wtedy (i to od razu) gdy nie ma więcej obszarów, które odnoszą się do niej.Możesz wymusić unieważnienie area_id przez przekazanie go do funkcji delete_area(). I znowu, leżąca pod spodem pamięć jest zwalniana tylko wtedy jeżeli twój obszar odnosi się do tej pamięc jako ostatni..
Usuwanie obszaru, czy to wprost przez delete_area(), czy dlatego, że Twoja aplikacja kończy działanie, nigdy nie dotyczy stanu innych obszarów, które były z niego klonowane.
|
Be Book,
...w ślicznym HTML...
dla BeOS wydanie 5
Copyright © 2000 Be, Inc. Wszelkie prawa zastrzeżone.