API jądra Linux

API jądra Linux
Przejdziemy przez interfejs programowania aplikacji Linux, API. Kernel Linux zapewnia wywołania systemowe, których można użyć do wykonania zadania przez jądro. Omówmy kilka powszechnie używanych wywołań systemowych Linuksa.

Opis:

Kernel Linux zapewnia zestaw lub listę funkcji, które mogą być używane przez programy przestrzeni użytkowników do korzystania z usług jądra Linux.

Schemat blokowy wygląda jak następujące:

Niektóre z nielicznych powszechnie używanych połączeń systemowych są otwarte, zamykane, odczytane i zapisywane. Są to podstawowe połączenia systemowe dostarczone przez jądro Linux. Każde zadanie jest wykonywane za pośrednictwem pliku w Linux. Tak więc podstawowe operacje w dowolnym pliku można wykonać poprzez otwarte, zamknięte, odczytane i zapisu.

Weźmy prawdziwy przykład, w którym chcemy wydrukować „Hello World” na konsoli szeregowej. Aby osiągnąć to zadanie za pośrednictwem połączeń systemowych, musimy otworzyć plik urządzenia dla konsoli w /dev. Po zlokalizowaniu pliku urządzenia dla konsoli lub UART możemy użyć otwartego wywołania systemu, aby otworzyć urządzenie.

Oto składnia wywołania otwartego systemu:

int Open (const char *pathName, int flags);
int Open (const char *pathName, int flags, tryb tryb_t);

Z tej składni pierwszym argumentem jest ścieżka pliku, którą chcemy otworzyć. W naszym przypadku jest to plik urządzenia, który zlokalizowaliśmy jako urządzenie konsolowe. W następnym argumencie flagi zapewniają użytkownikowi pewną elastyczność do gry z plikiem. Niewiele przykładów flag to O_Creat, O_Append itp. Te flagi mają określone znaczenie i cel, a dyskusja nie jest w zakresie tej dyskusji. Aby uzyskać więcej informacji na temat flag i parametrów, odnieś się strony jądra.

Po pomyślnym otwarciu pliku musimy użyć wywołania systemu zapisu, aby wysłać „Hello World” do urządzenia konsolowego. Prototyp wywołania systemu zapisu jest następujący:

ssize_t zapis (int fd, const void *buf, size_t Count);

Pierwszym parametrem wywołania systemu zapisu jest FD, który jest opisem pliku. „FD” jest nam przekazywane przez otwarte system systemu. Po pomyślnym otwarciu pliku powinniśmy uzyskać deskryptor pliku. Ten FD jest używany do zapisywania danych.

Drugi parametr to adres buforowy dla danych do urządzenia konsolowego. W naszym przypadku dane testowe to „Hello World”.

Ostatni parametr to całkowita liczba bajtów, które użytkownik chce napisać na urządzeniu konsolowym. W naszym przypadku liczba bajtów ma rozmiar „Hello World”. Możemy użyć funkcji sizeof lub funkcji strlen, aby uzyskać liczbę bajtów. Powinniśmy zachować ostrożność podczas korzystania z Strlen. Ta funkcja ignoruje znak terminatora łańcucha, taki jak „\ 0”. Tak więc, czytając ciąg, musimy upewnić się, że znak zerowy jest właściwie obsługi. W przeciwnym razie skończymy z usterką segmentacji.

Teraz zaimplementujmy część kodu tego przykładu. Najpierw musimy zlokalizować konsolę szeregową lub urządzenie UART. W maszynie to, czego używamy, ma szeregowe urządzenie Tty AS/dev/pts/0. Tak więc, jak omówiono, najpierw musimy otworzyć ten plik. Musimy również dołączyć twardszy plik, który zawiera deklarację otwartego systemu.

Nasz kod otwierania pliku urządzenia wygląda jak następujące:

#włączać
fd = Open („/dev/pts/0”, o_wronly);

Następnie, kiedy chcemy wywołać wywołanie systemu zapisu, używamy FD dostarczonego przez Open. Nasza funkcja zapisu wygląda jak następujące:

#włączać
char *data = „Hello World”;
Write (FD, Data, Strlen (Data) +1);

Poprzedni kod Snippet pisze „Hello World” do konsoli szeregowej, którą zlokalizowaliśmy i chcemy napisać.

Złóżmy wszystkie elementy:

#włączać
#włączać
#włączać
#włączać
#włączać
int main ()

int fd; int rc;
char *data = „Hello World”;
fd = Open („/dev/pts/0”, o_wronly);
if (fd<0)

printf („Plik otwierający błąd:%D”, FD);
wyjście (-1);

rc = zapis (fd, dane, strlen (dane) +1);
if (rc<0)

printf („Plik pisania błędów:%D”, RC);
wyjście (-1);

Zamknij (FD); // Operacja pliku jest wykonywana, zamknij plik.
powrót 0;

Kompilowanie poprzedniego programu jest takie samo, jak opracowanie innych programów C, takich jak następujące:

GCC TEST_WRITE.C -O test_write.

Test_write.C to nazwa pliku do naszego kodu C.

Po kompilacji otrzymujemy wykonywalne z nazwą test_write.

Patrz następujący migawka:

Po uruchomieniu skompilowanego i wygenerowanego binarnego, mamy następujące dane wyjściowe.

Nasze wyjście programu jest podświetlone odważnymi literami. Poniżej znajduje się migawka w celach informacyjnych:

Do tej pory widzieliśmy przykład, w którym używamy interfejsu API Linux do wyświetlania ciągu testowego do konsoli. To jest prosty przykład. Istnieje wiele innych ofert dostarczanych przez połączenie systemowe. Niewiele wywołań systemowych, które są dostarczane przez Linux, jest następujące:

  • Czytać: Czytanie z pliku.
  • pisać: Pisanie do pliku.
  • otwarty: Otwieranie pliku.
  • zamknąć: Zamknięcie pliku.
  • głosowanie: Sondowanie urządzenia do zmiany stanu.
  • Lseek: Poszukiwanie konkretnego przesunięcia w pliku.
  • MMAP: Mapowanie pamięci wirtualnej na pamięć fizyczną.
  • BRK: Zmień rozmiar segmentu.
  • IOCTL: Urządzenia sterujące.
  • dostęp: Dostęp do uzyskania uprawnień pliku.
  • rura: Odnosi się do tworzenia rur.

i wiele więcej.

To jest ogromna lista funkcji dostarczanych przez jądro Linux. Widzieliśmy i omawialiśmy bardzo niewiele. Pełna lista połączeń systemowych, które są dostarczane przez jądro.

Wniosek

Omówiliśmy o połączeniach systemowych, które jest sposobem na poproszenie jądra o wykonanie zadań dla programów przestrzeni użytkowników. Bez połączenia systemowego nie będą możliwe, aby programy przestrzeni użytkowników wykonały zadanie przez jądro. Przyjęliśmy proste zadanie lub przykład pisania danych testowych „Hello World” do urządzenia szeregowego. Zastosowaliśmy otwartą, pisz i zamykanie interfejsów API jądra, aby wykonać zadanie w ręku. Jedną najważniejszą rzeczą jest sprawdzenie wartości zwrotu połączeń systemowych. Kernel zapewnia odpowiednie wartości zwrotne w celu wyjaśnienia przyczyny awarii funkcji. Użytkownik może uzyskać pomysł na powód porażki, widząc wartości zwrotu z wywołania systemowego. Wartości powrotne mają pewne określone znaczenie i są dobrze schwytane w dokumentacji jądra.