niedziela, 1 sierpnia 2010

Podstawy programowania w systemach UNIX/LINUX cz. 1

W pierwszej kolejności zajmiemy się obsługą systemu plików.System plików to daje użytkownikowi możliwość dostępu do danych przechowywanych w pamięci pomocniczej(np. dysk). Jest on także odpowiedzialny za zarządzanie plikami i przydzielanie im pamięci, za administrowanie pamięcią wolna oraz sterownie dostępem do plików.Procesy(wykonujące się programy) komunikują się z systemem plików poprzez funkcje systemowe.

Jądro systemu operacyjnego UNIX udostępnia nam dwie podstawowe operacje zapis i odczyt , przy pomocy funkcji systemowych write i read .Trzeba wiedzieć ,że plik traktowany jest jako tablica bajtów dzięki temu możemy operować na nim z dokładnością co do bajtu.

Aby móc wykonywać operacje na pliku trzeba najpierw go otworzyć ,do tego celu posłuży nam funkcja open. Zwraca ona deskryptor pliku,zapytacie pewnie czym jest ów "deskryptor" . Jest to liczba ,która "opisuje" , a mówiąc bardziej precyzyjnie identyfikuje plik. Standardowo deskryptory 0, 1, 2 przydzielone są standardowemu wejściu,wyjściu i wyjściu diagnostycznemu.

Przy otwieraniu pliku przekazywany jest tryb otwarcia , który określa dopuszczalne operacje jakie można wykonać w związku z tym otwarciem (tylko zapis, tylko odczyt etc.)

Poniżej zamieszczam definicje najważniejszych funkcji systemowych:

int creat(const char *pathname, mode_t mode)

Wartości zwracane:
poprawne wykonanie funkcji: deskryptor otwartego pliku
zakończenie błędne: - 1

Argumenty funkcji:
pathname – wskaźnik do napisu zawierającego nazwę ścieżki pliku, który ma być otwarty
mode – prawa dostępu (np. 0640)

Opis:
Funkcja tworzy nowy plik, którego lokalizacja zależy od parametru pathname , a prawa dostępu od parametru mode .



int open(const char *pathname, int flags[, mode_t mode])

Wartości zwracane:
poprawne wykonanie funkcji: deskryptor otwartego pliku
zakończenie błędne: - 1

Argumenty funkcji:
pathname – wskaźnik do napisu zawierającego nazwę ścieżki pliku, który ma być otwarty
flags – metoda dostępu
• O_RDONLY – otwarcie w trybie tylko do odczytu
• O_WRONLY – otwarcie w trybie tylko do zapisu
• O_RDWR –- otwarcie w trybie do odczytu i do zapisu
Argument flags może być połączony bitowym OR z jedną (lub więcej) z następujących wartości:
• O_CREAT – utworzenie pliku, jeśli plik jeszcze nie istnieje,
• O_TRUNC – obcięcie pliku, jeśli plik istnieje i otwierany jest w trybie
O_WRONLY lub O_RDWR,
• O_EXCL – powoduje zgłoszenie błędu jeśli plik już istnieje i otwierany jest z flagą O_CREAT
• O_APPEND – operacje pisania odbywają się na końcu pliku.
mode – prawa dostępu, jest to argument opcjonalny

Opis:
Parametr wejściowy pathname jest nazwą (w szczególności pełną nazwą ścieżkową) pliku, parametr wejściowy flags oznacza tryb otwarcia pliku pliku i może mieć następujące wartości: O_RDONLY, O_WRONLY, O_RDWR .



int close(int fd)

Wartości zwracane:
poprawne wykonanie funkcji: 0
zakończenie błędne: - 1

Argumenty funkcji:
fd – deskryptor zamykanego pliku

Opis:
Funkcja zamyka deskryptor pliku przekazany przez parametr fd .



int read(inf fd, void *buf, size_t count)

Wartości zwracane:
poprawne wykonanie funkcji: rzeczywista liczba bajtów, jaką udało się odczytać
zakończenie błędne: - 1

Argumenty funkcji:
fd – deskryptor pliku z którego mają zostać odczytane dane
buf – adres bufora znajdującego się w segmencie danych procesu, do którego zostaną przekazane dane odczytane z pliku w wyniku wywołania funkcji read
count – ilość bajtów do odczytania

Opis:
Odczyt danych z pliku. Funkcja powoduje odczyt count bajtów z otwartego pliku, identyfikowanego przez deskryptor fd , począwszy od bieżącej pozycji wskaźnika do pliku i umieszczenie ich pod adresem buf w przestrzeni adresowej procesu. Funkcja zwraca liczbę bajtów na której udało się wykonać operację (zero oznacza koniec pliku). Odczyt powoduje zmianę wskaźnika bieżącej pozycji w pliku. Po otwarciu pliku wskaźnik ten ustawiony jest na 0, czyli na początek pliku, a po kolejnych operacjach przesuwa się w kierunku końca pliku o tyle bajtów ile udało się odczytać.




int write(inf fd, void *buf, size_t count)

Wartości zwracane:
poprawne wykonanie funkcji: rzeczywista liczba bajtów, jaką udało się zapisać
zakończenie błędne: - 1

Argumenty funkcji:
fd – deskryptor pliku do którego mają zostać zapisane dane
buf – adres bufora znajdującego się w segmencie danych procesu, z którego zostaną pobrane dane zapisane przez funkcję write
count – ilość bajtów do zapisania
Opis:

Funkcja powoduje zapis count bajtów do otwartego pliku, identyfikowanego
przez deskryptor fd , począwszy od bieżącej pozycji wskaźnika do pliku i umieszczenie ich pod
adresem buf w przestrzeni adresowej procesu. Funkcja zwraca liczbę bajtów na której udało się
wykonać operację.
Podobnie jak dla funkcji read zapis powoduje zmianę wskaźnika bieżącej pozycji w pliku.



Czas na praktykę. Napiszemy prosty program , którego zadaniem będzie
kopiowanie pliku podanego przez użytkownika:



#include fcntl.h 
#include stdio.h 
#define BUF_SIZE 1024
int main(int argc, char* argv[]){
char buf[BUF_SIZE];
int desc_1,desc_2;
int odczytano=0;
if (argc<3){ 
                fprintf(stderr, "Zla ilosc argumentow !!");   
                exit(1); 
        }

desc_1 = open(argv[1], O_RDONLY); 
        if (desc_1 == -1){ 
                perror("Blad otwarcia pliku zrodlowego"); 
                exit(1); 
        } 
 desc_1 = creat(argv[2], 0640); 
        if (desc_1 == -1){ 
                perror("Blad utworzenia pliku docelowego"); 
                exit(1); 
         } 
while((odczytano = read(desc_1, BUF_SIZE, MAX)) > 0){ 
        if (write(desc_2, buf, lbajt) == -1){ 
                perror("Blad zapisu pliku docelowego"); 
                exit(1); 
} 
} 
if (odczytano== -1){ 
                perror("Blad odczytu pliku zrodlowego"); 
                exit(1); 
} 
if (close(desc_1) == -1 || close(desc_2) == -1){ 
                perror("Blad zamkniecia pliku"); 
                exit(1); 
} 
exit(0);
}