Norbert Langner

Norbert Langner

My homepage @ PUT

(PSiW) API POSIX - Wstęp

Czas rozpocząć przygodę z API POSIX. POSIX to akronim od Portable Operating System Interface (Przenośny Interfejs Systemu Operacyjnego), który oznacza rodzinę standardów definiujących cechy wspólne dla systemów z rodziny UNIX. Linux, w prawdzie, nie jest systemem Uniksowym, ale zachowuje z nim częściową zgodność. Dlatego też programy, które będziemy pisać w tej części zajęć powinny działać zarówno na Linuksie, jak i systemach z rodziny BSD oraz innych Uniksach. Z racji kompatybilności wykorzystanych funkcji z API, poniżej będę odwoływał się do nazwy Unix, chyba, że sposób działania danej funkcji w Linuksie znacząco się różni.

Hello Unix

Korzystanie z API systemowego w systemach Uniksowych nie różni się znacząco od używania innych bibliotek w języku C. Co więcej, w ramach dystrybucji naszego systemu możemy mieć dostęp do pełnej dokumentacji funkcji systemowych, z czego będziemy często korzystać. Na początek napiszemy prosty program, który otworzy plik wskazany w parametrze wywołania programu. Warto zaznaczyć, że większość języków i bibliotek zawiera własne mechanizmy obsługi plików. W wykorzystywanym C++ jest to klasa fstream, w C będzie to typ 1) FILE i funkcje typu fopen, czy fclose.

Do otwierania plików służy funkcja open. W tej części nie będziemy dokładnie przyglądać się jej wywołaniu - tym zajmiemy się w następnej sekcji. Jako pierwszy parametr podajemy ścieżkę do pliku, który chcemy otworzyć, a drugi parametr ustalimy jako stałą O_RDONLY, która otworzy nam wskazany plik w trybie tylko do odczytu. Dokładną dokumentację tej funkcji systemowej możemy znaleźć w podręczniku użytkownika. Wyświetlimy go, wywołując w terminalu komendę man 2 open.

Funkcja open zwraca nam liczbę całkowitą, którą tutaj nazywamy deskryptorem pliku. Jednakże, częstą konwencją w API POSIX jest także zwracanie wartości -1, gdy wywołanie funkcji zakończy się niepowodzeniem. Taka wartość raczej nie mówi nam wiele na temat błędu, który wystąpił, dlatego system operacyjny przechowuje szczegóły ostatniego wywołania funkcji systemowych. Kod liczbowy ostatniego błędu możemy odczytać funkcją errno. Wartość liczbowa nie powie zbyt wiele użytkownikowi, należałoby więc jakoś tę wartość zinterpretować. Na szczęście, dostępna jest funkcja perror, która pozwala nam zdefiniować komunikat dla użytkownika programu, do którego doklejany jest tekstowy opis ostatniego błędu. Więcej informacji, jak zwykle, znajdziemy w podręczniku - tym razem w rozdziale trzecim (man 3 perror).

Ostatnią rzeczą, o której musimy pamiętać, to załączenie odpowiednich plików nagłówkowych w kodzie naszego programu. Zawsze możemy to ustalić na stronach manuala, jednak dla naszego, prostego programu będzie to, po prostu #include <fcntl.h>.

Kompletny kod programu znajduje się w repozytorium, w folderze 01_introduction/helloposix.

Zadania

  1. Przetestuj działanie programu dla następujących przypadków:
    • nie podano nazwy pliku do otwarcia,
    • podany plik nie istnieje,
    • uprawnienia pliku nie pozwalają na jego odczyt.
  2. Zamień flagę `O_RDONLY` na `O_WRONLY` w kodzie programu. Spróbuj otworzyć plik, do którego nie masz prawa zapisu.
  3. Sprawdź wynik pracy programu (w bashu komenda `echo $?`).
1)
Standard języka C nie przewiduje dokładnej specyfikacji typu FILE. W implementacji Uniksowej jest to struktura. Dokładniejszy opis znajduje się na cppreference.com.