SO2 instrukcja 9


Instrukcja do laboratorium Systemów Operacyjnych
(semestr drugi)
Ćwiczenie dziewiąte
Temat: Operacje na plikach, zajmowanie plików
Opracowanie:
mgr inż. Arkadiusz Chrobot
dr inż. Grzegorz Aukawski
Wprowadzenie
1. Niskopoziomowa obsługa plików, dostęp współbieżny do plików
Programista piszący programy dla środowiska uniksowego ma do wyboru dwa
rodzaje obsługi plików. Może się posługiwać niskopoziomowymi funkcjami
dostarczanymi przez system, lub podprogramami, które oferują biblioteki
wejścia  wyjścia większości języków programowania. Pierwsze rozwiązanie
pozwala na bezpośredni dostęp do plików (tzn. niebuforowany) przy użyciu
deskryptorów plików. Pomimo pozornie małej funkcjonalności to właśnie ten
sposób wykonywania operacji wejścia  wyjścia jest zalecany jeśli z plikiem
pracuje kilka współbieżnych procesów lub wątków. Posługiwanie się funkcjami
systemowymi nie stanowi jednak samo w sobie rozwiązania problemu
współbieżnego dostępu do plików. Istnieją pomocnicze mechanizmy nazywane
zajmowaniem pliku, które pozwalają na zakładanie blokad uniemożliwiających
dostęp do plików lub fragmentów plików innym procesom. Są dwa rodzaje tych
mechanizmów: zajmowanie obowiązkowe (ang. mandatory) i zalecane (ang.
advisory). Pierwszy został wprowadzony do wersji System V Uniksa i jest
włączony do standardu POSIX. Drugi pojawił się w wersji BSD Uniksa.
Zajmowanie obowiązkowe pliku (zwane także narzuconym), wymusza na
systemie operacyjnym kontrolowanie, czy procesy nie naruszają nałożonych na
plik blokad. Blokady w tym przypadku są związane z plikiem, tzn. po
zakończeniu procesu nie są usuwane. Zajmowanie zalecane (zwane także
doradczym) nie wymusza sprawdzania poprawności operacji na pliku przez
jądro systemu. O to muszą zadbać procesy odwołujące się do pliku. Blokady te
związane są z procesem1, a więc po jego zakończeniu są usuwane. Linux
pozwala na stosowanie obu rodzajów zajmowania, aczkolwiek domyślnie
stosowane jest zajmowanie zalecane. Aby móc posługiwać się zajmowaniem
obowiązkowym należy zamontować system plików z odpowiednimi flagami
i odpowiednio skonfigurować prawa dostępu do plików. Istnieją dwa rodzaje
blokad: dzielone lub do czytania, które pozwalają kilku procesom czytać
współbieżnie z pliku (całego lub części), ale zakazują zapisywania i blokady
wyłączne lub do zapisu, które pozwalają tylko jednemu procesowi na zapis do
pliku (całego lub części). Proces będący właścicielem blokady może zmienić jej
typ. Jeżeli na pliku lub jego obszarze istnieje blokada współbieżna, to inny
proces na ten sam plik lub obszar może nałożyć swoją blokadę do czytania, ale
nie może nałożyć blokady do zapisu. Jeśli na pliku lub obszarze pliku istnieje
blokada wyłączna to żaden proces nie może nałożyć na ten plik (obszar) żadnej
innej blokady.
1 Dokładniej z relacją proces  plik, w przypadku Linuksa jest ona związana z obiektem pliku.
2
2. Funkcje i struktury danych
funkcja open()  otwiera plik. Jako argumenty pobiera ścieżką dostępu do
pliku i flagi. Może również pobierać prawa dostępu, jeśli plik nie istnieje
i ma być utworzony. Wartością zwracaną przez funkcję jest deskryptor
pliku. Szczegóły: man 2 open.
funkcja create()  tworzy nowy plik i otwiera go do zapisu, czyli dubluje
częściowo działanie open(). Szczegóły: man creat.
funkcje dup() i dup2()  pozwalają uzyskać kopię deskryptora pliku.
Deskryptor oryginalny i powstały w wyniku działania dup() lub dup2() nie
dzielą jedynie ze sobą flagi close_on_exit. Szczegóły: man dup lub man
dup2.
funkcja read()  odczytuje z pliku określoną ilość informacji. Jako
argumenty przyjmuje deskryptor pliku, adres zmiennej do której ma
zapisać informacje, oraz ilość informacji jaką ma przeczytać wyrażoną
w bajtach. Wartością zwracaną przez funkcję jest natomiast liczba
przeczytanych bajtów. Może zostać zastosowana również do odczytu
standardowego wejścia, którego deskryptor wynosi zero. Szczegóły: man
2 read.
funkcja write()  zapisuje dane do pliku. Przyjmuje takie same argumenty
jak read(), może być użyta do zapisu na standardowe wyjście (deskryptor
1) lub standardowe wyjście diagnostyczne (deskryptor 2). Wartością
zwracaną przez funkcję jest liczbę zapisanych bajtów. Szczegóły: man
2 write.
funkcja close()  zamyka plik związany z przekazanym jej jako argument
deskryptorem. W razie niepowodzenia zwraca wartość -1 w przeciwnym
przypadku wartość 0.
funkcja lseek()  zmienia wartość wskaznika pliku. Szczegóły: man lseek.
funkcja flock()  zakłada lub usuwa blokadę z pliku. Jest związana
z mechanizmem zalecanego zajmowania. Blokadę można nałożyć tylko
i wyłącznie na całość pliku. Szczegóły: man 2 flock.
funkcja lockf()  związana z mechanizmem zajmowania obowiązkowego.
3
W Linuksie stanowi interfejs nałożony na funkcję fcntl(). Szczegóły: man
lockf.
funkcja fcntl()  generalnie pozwala na manipulowanie deskryptorem
otwartego pliku. Pozwala również zakładać blokady związane
z zajmowaniem obowiązkowym, lecz domyślnie stosuje zajmowanie
doradcze (podobnie jak lockf()). Pozwala na zajmowanie ściśle określonych
obszarów plików lub całych plików. Szczegóły: man fcntl.
funkcja fsync() - szereguje bufory ze zmodyfikowanymi danymi oraz
metadanymi pliku i zapisuje je na dysk. Szczegóły: man fsync.
funkcja fdatasync() - działa podobnie jak fsync(), ale zapis ograniczony jest
wyłącznie do zmodyfikowanych danych. Szczegóły: man fdatasync
Zadania
1. Napisz program, który przepisze z istniejącego pliku tekstowego czterdzieści
znaków z początku i czterdzieści znaków z końca do nowego pliku.
2. Stwórz plik tekstowy wielkości 512 bajtów, z  dziurą w środku.
3. Zademonstruj działanie funkcji replikującej deskryptory plików.
4. Zademonstruj działanie funkcji flock() na przykładzie, w którym kilka procesów
współbieżnych będzie się ubiegało o możliwość zapisu lub odczytu z pliku.
5. Powtórz zadanie trzecie używając fcntl() i blokując wybrane fragmenty pliku.
6. Napisz program, który przeczyta i wypisze na ekran plik tekstowy o dowolnej
wielkości. Nazwę pliku należy przekazywać jako argument wywołania
programu. W programie nie wolno korzystać z funkcji printf() ani pokrewnych.
7. Napisz odpowiednik programu  cp .
8. Napisz program, w którym dwa procesy będą zapisywały do jednego pliku,
a trzy będą odczytywały. Zastosuj zajmowanie zalecane do synchronizacji pracy
procesów.
9. Napisz program, który otworzy do odczytu wskazany plik tekstowy, a następnie
wywoła funkcję fork(). Jeden z powstałych procesów policzy sumę liczb
parzystych znalezionych w otwartym pliku, a drugi liczb nieparzystych.
10.Napisz dwa programy: pierwszy będzie generował losowe liczby i zapisywał je
porcjami do pliku, drugi działając współbieżnie z pierwszym będzie odczytywał
je i szukał wartości maksymalnej. Do blokowania fragmentów pliku należy użyć
4
funkcji fcntl().
11.Napisz program, w którym stworzysz cztery procesy. Każdy z tych uzyska
kopię deskryptora do pojedynczego pliku, przy czym jeden proces będzie do
tego pliku pisał, a pozostałe będą czytały.
12.Napisz program, który będzie zapisywał do pliku informacje tekstowe porcjami
po 4 KiB w trzech trybach: z wykorzystaniem funkcji fsync(), z użyciem
fdatasync() i bez stosowania żadnej z tych funkcji. Dokonaj pomiaru czasu
zapisu dla każdego z tych przypadków. Do wyznaczenia czasu zapisu użyj
funkcji time() (Szczegóły: man 2 time).
5


Wyszukiwarka

Podobne podstrony:
SO2 instrukcja 4 Kolejki komunikatów
SO2 instrukcja 4
SO2 instrukcja 8
SO2 instrukcja 5
SO2 instrukcja 2 Procesy i sygna éy
SO2 instrukcja 7
SO2 instrukcja 6 Pamięć dzielona
SO2 instrukcja 1
SO2 instrukcja
SO2 instrukcja 3 Łącza komunikacyjne, nienazwane i nazwane

więcej podobnych podstron