Jesteś tutaj

Linux Kernel. Przewodnik programisty

Dołącz do grona twórców popularności Linuksa

Fenomen Linuksa polega na tym, że jest on dziełem programistów z całego świata. Każdy może dopisać do niego nową funkcję lub udoskonalić istniejące. Jeśli Linux nie obsługuje urządzenia zainstalowanego w Twoim komputerze -- możesz zaimplementować jego obsługę, pisząc własny moduł jądra.

Programowanie jądra systemu Linux nie wymaga żadnych niezwykłych zdolności. Choć jest ono rozległym projektem informatycznym, w żaden sposób nie różni się od innych projektów tego typu. Oczywiście, samodzielne napisanie choćby kawałka kodu jądra wymaga nauki, ale napisany dotychczas kod nie jest w żaden sposób wyjątkowy ani niezrozumiały. Podstawowym materiałem pomocniczym, niezwykle przydatnym przy opanowywaniu tajników programowania jądra, jest istniejący już kod źródłowy, dostępny dla wszystkich. Jednakże samo poznawanie kodu nie wystarczy -- należy również zdobyć wiedzę dotyczącą zasad funkcjonowania systemu operacyjnego i pełnionych przez niego funkcji.

Książka "Linux Kernel. Przewodnik programisty" została napisana po to, aby pomóc programistom w poznaniu zasad tworzenia kodu modułów jądra. Szczegółowo omawia podsystemy i funkcje jądra Linuksa, ich projekt i implementację. Autor książki porusza również zagadnienia związane z projektowaniem systemów operacyjnych.

Książka opiera się na wersji 2.6 jądra systemu Linux i zawiera informacje dotyczące następujących tematów:

  • Podstawowe zasady programowania jądra
  • Zarządzanie procesami
  • Algorytmy szeregowania zadań
  • Wywołania systemowe
  • Przerwania
  • Metody synchronizacji jądra
  • Zarządzanie czasem i pamięcią
  • Operacje wejścia -- wyjścia
  • Diagnostyka kodu jądra
  • Przenośność kodu

Stwórz poprawne funkcje jądra Linuksa i zaimplementuj je w odpowiedni sposób.

SPIS TREŚCI:

O Autorze (13)
Przedmowa (15)

Wstęp (17)
Słowo od Autora (19)
Rozdział 1. Jądro systemu Linux - wprowadzenie (23)

  • Wprowadzenie do systemu Linux (25)
  • Przegląd systemów operacyjnych (26)
  • Jądro Linuksa a jądro klasycznego systemu uniksowego (28)
  • Oznaczenia wersji jądra Linuksa (29)
  • Społeczność programistów jądra systemu Linux (31)
  • Odmienność jądra (31)
    • Brak biblioteki libc (32)
    • GNU C (32)
    • Brak mechanizmu ochrony pamięci (34)
    • Niemożność (łatwego) korzystania z operacji zmiennoprzecinkowych (35)
    • Ograniczony co do rozmiaru i stały stos (35)
    • Synchronizacja i współbieżność (35)
    • Znaczenie przenośności (36)
  • Kompilowanie jądra (36)
  • Zanim zaczniemy (38)

Rozdział 2. Zarządzanie procesami (39)

  • Deskryptor procesu i struktura zadania (40)
    • Alokacja deskryptora procesu (41)
    • Przechowywanie deskryptora procesu (42)
    • Stan procesu (43)
    • Manipulowanie bieżącym stanem procesu (44)
    • Kontekst procesu (45)
  • Tworzenie procesu (46)
    • Kopiowanie przy zapisie (47)
    • Wywołanie fork() (47)
    • Wywołanie vfork() (49)
  • Wątki w systemie Linux (49)
    • Wątki jądra (51)
  • Zakończenie procesu (52)
    • Usuwanie deskryptora procesu (53)
    • Problem zadań osieroconych (54)

Rozdział 3. Szeregowanie zadań (57)

  • Strategia postępowania (58)
    • Procesy ograniczone wejściem-wyjściem a procesy ograniczone procesorem (58)
    • Priorytet procesu (59)
    • Kwant czasu (60)
    • Wywłaszczanie procesu (61)
    • Strategia szeregowania w działaniu (61)
  • Algorytm szeregujący (62)
    • Kolejka procesów gotowych do uruchomienia (62)
    • Tablice priorytetów (65)
    • Przeliczanie kwantów czasu (66)
    • Wywołanie schedule() (67)
    • Wyznaczanie nowego priorytetu i kwantu czasu (68)
    • Zawieszanie i pobudzanie procesów (71)
    • Równoważenie obciążenia (73)
  • Wywłaszczanie i przełączanie kontekstu (75)
    • Wywłaszczanie procesu użytkownika (76)
    • Wywłaszczenie jądra (76)
  • Czas rzeczywisty (77)
  • Wywołania systemowe związane z szeregowaniem (78)
    • Wywołania wpływające na strategię szeregowania i wartości priorytetów (79)
    • Wywołania systemowe sterujące kojarzeniem procesów z procesorami (80)
    • Odstąpienie procesora (80)

Rozdział 4. Wywołania systemowe (81)

  • API, POSIX i biblioteka C (82)
  • Wywołania systemowe (83)
    • Numery wywołań systemowych (84)
    • Wydajność wywołania systemowego (85)
  • Procedura obsługi wywołań systemowych (85)
    • Oznaczanie właściwego wywołania systemowego (86)
    • Przekazywanie argumentów (86)
  • Implementacja wywołania systemowego (87)
    • Weryfikacja argumentów (87)
  • Kontekst wywołania systemowego (89)
    • Wiązanie wywołania systemowego (90)
    • Inicjowanie wywołania systemowego z przestrzeni użytkownika (92)
    • Cztery powody, aby nie implementować wywołań systemowych (93)

Rozdział 5. Przerwania i procedury obsługi przerwań (95)

  • Przerwania (95)
  • Procedury obsługi przerwań (96)
    • Połówki górne i dolne (97)
  • Rejestrowanie procedury obsługi przerwania (98)
    • Zwalnianie procedury obsługi przerwania (100)
  • Tworzenie procedury obsługi przerwań (100)
    • Procedury obsługi przerwań współużytkowanych (102)
    • Prawdziwa procedura obsługi przerwania (103)
    • Kontekst przerwania (104)
  • Implementacja obsługi przerwań (105)
  • /proc/interrupts (108)
  • Kontrola przerwań (109)
    • Wyłączanie i włączanie przerwań (110)
    • Blokowanie konkretnej linii przerwania (111)
    • Stan systemu przerwań (112)

Rozdział 6. Dolne połówki i czynności odroczone (115)

  • Połówki dolne (116)
    • Po co dolne połówki? (117)
    • Świat dolnych połówek (117)
  • Przerwania programowe (120)
    • Implementacja przerwań programowych (120)
    • Korzystanie z przerwań programowych (123)
  • Tasklety (125)
    • Implementacja taskletów (125)
    • Korzystanie z taskletów (128)
    • Wątek jądra ksoftirqd (130)
    • Dawny mechanizm BH (132)
  • Kolejki robót (133)
    • Implementacja kolejek robót (133)
    • Korzystanie z kolejek robót (137)
    • Dawny mechanizm kolejkowania zadań (140)
  • Jak wybrać implementację dolnej połówki? (140)
  • Blokowanie pomiędzy dolnymi połówkami (142)
    • Wyłączanie dolnych połówek (142)

Rozdział 7. Wprowadzenie do synchronizacji jądra (145)

  • Sekcje krytyczne i przeplot operacji (146)
    • Po co ta ochrona? (146)
  • Blokowanie (147)
    • Skąd się bierze współbieżność? (149)
    • Co wymaga zabezpieczania? (150)
  • Zakleszczenia (151)
  • Rywalizacja a skalowalność (154)
  • Blokowanie we własnym kodzie (155)

Rozdział 8. Metody synchronizacji jądra (157)

  • Operacje niepodzielne (157)
    • Niepodzielne operacje na liczbach całkowitych (158)
    • Niepodzielne operacje bitowe (160)
  • Rygle pętlowe (162)
    • Inne metody blokowania ryglami pętlowymi (165)
    • Rygle pętlowe a dolne połówki (166)
  • Rygle pętlowe R-W (166)
  • Semafory (168)
    • Tworzenie i inicjalizowanie semaforów (170)
    • Korzystanie z semaforów (171)
  • Semafory R-W (172)
  • Zmienne sygnałowe (174)
  • Blokada BKL (Big Kernel Lock) (174)
  • Blokady sekwencyjne (176)
  • Blokowanie wywłaszczania (177)
  • Bariery (178)

Rozdział 9. Liczniki i zarządzanie czasem (183)

  • Czas z punktu widzenia jądra (184)
  • Częstotliwość taktowania - HZ (185)
    • Optymalna wartość HZ (186)
  • Chwilki (188)
    • Wewnętrzna reprezentacja zmiennej jiffies (190)
    • Zawijanie zmiennej jiffies (191)
    • HZ a przestrzeń użytkownika (192)
  • Zegary i liczniki sprzętowe (193)
    • Zegar czasu rzeczywistego (193)
    • Zegar systemowy (193)
  • Procedura obsługi przerwania zegarowego (194)
  • Data i godzina (196)
  • Liczniki (198)
    • Korzystanie z liczników (199)
    • Liczniki i sytuacje hazardowe (201)
    • Implementacja licznika (201)
  • Opóźnianie wykonania (202)
    • Oczekiwanie w pętli aktywnej (202)
    • Krótkie opóźnienia (204)
    • Funkcja schedule_timeout() (205)

Rozdział 10. Zarządzanie pamięcią (209)

  • Strony (209)
  • Strefy (211)
  • Pozyskiwanie stron pamięci (213)
    • Pozyskiwanie czystych stron pamięci (214)
    • Zwalnianie stron (215)
  • Funkcja kmalloc () (216)
    • Znaczniki gfp_mask (217)
  • Funkcja kfree() (221)
  • Funkcja vmalloc () (222)
  • Alokator plastrowy (223)
    • Zadania alokatora plastrowego (224)
  • Interfejs alokatora plastrowego (227)
  • Statyczne przydziały na stosie (230)
  • Odwzorowanie pamięci wysokiej (231)
    • Odwzorowanie trwałe (231)
    • Odwzorowania czasowe (232)
  • Jak metodę przydziału wybrać? (233)

Rozdział 11. Wirtualny system plików (235)

  • Wspólny interfejs systemu plików (235)
  • Warstwa abstrakcji systemu plików (236)
  • Uniksowy system plików (237)
  • Obiekty VFS i ich struktury danych (238)
    • Inne obiekty warstwy VFS (239)
  • Obiekt bloku głównego (240)
    • Operacje bloku głównego (241)
  • Obiekt i-węzła (243)
    • Operacje i-węzła (245)
  • Obiekt wpisu katalogowego (247)
    • Stan wpisu katalogowego (249)
    • Bufor wpisów katalogowych (249)
    • Operacje na wpisach katalogowych (251)
  • Obiekt pliku (252)
    • Operacje na plikach (253)
  • Struktury danych systemu plików (256)
  • Struktury danych procesu (257)
  • Systemy plików w Linuksie (259)

Rozdział 12. Blokowe urządzenia wejścia-wyjścia (261)

  • Anatomia urządzenia blokowego (262)
  • Bufory i nagłówki buforów (263)
  • Struktura bio (266)
    • Stare a nowe (268)
  • Kolejki zleceń (269)
    • Zlecenia (269)
  • Zawiadywanie operacjami wejścia-wyjścia (269)
    • Zadania planisty operacji wejścia-wyjścia (270)
    • Winda Linusa (271)
    • Terminowy planista operacji wejścia-wyjścia (272)
    • Przewidujący planista operacji wejścia-wyjścia (274)

Rozdział 13. Przestrzeń adresowa procesu (277)

  • Deskryptor pamięci (279)
    • Przydział deskryptora pamięci (280)
    • Zwalnianie deskryptora pamięci (281)
    • Struktura mm_struct i wątki jądra (281)
  • Obszary pamięci (282)
    • Znaczniki VMA (283)
    • Operacje VMA (284)
    • Obszary pamięci na listach i w drzewach (285)
    • Obszary pamięci w praktyce (286)
  • Manipulowanie obszarami pamięci (288)
    • Funkcja find_vma() (288)
    • Funkcja find_vma_prev() (289)
    • Funkcja find_vma_intersection() (289)
  • Tworzenie interwału adresów - wywołania mmap() i do_mmap() (290)
    • Wywołanie systemowe mmap() (292)
  • Usuwanie interwału adresów - wywołania munmap() i do_munmap() (292)
    • Wywołanie systemowe munmap() (292)
  • Tablice stron (293)

Rozdział 14. Pamięć podręczna stron i opóźniony zapis stron w tle (295)

  • Pamięć podręczna stron (296)
    • Obiekt address_space (297)
  • Drzewo pozycyjne (300)
    • Tablica skrótów stron (300)
  • Pamięć podręczna buforów (301)
  • Demon pdflush (301)
    • bdflush i kupdated (303)
    • Eliminowanie przeciążenia, czyli po co w jądrze wiele wątków? (303)

Rozdział 15. Diagnostyka (305)

  • Od czego zacząć? (305)
  • Błędy w jądrze (306)
  • Funkcja printk() (307)
    • Wszechstronność funkcji printk() (307)
    • Ograniczenia funkcji printk() (307)
    • Poziomy rejestrowania (308)
    • Bufor komunikatów (309)
    • Demony syslogd i klogd (310)
    • Funkcja printk() a hakerzy jądra (310)
  • Błąd oops (310)
    • Polecenie ksymoops (312)
    • kallsyms (313)
  • Opcje diagnostyczne jądra (313)
    • Diagnostyka niepodzielności operacji (313)
  • Prowokowanie błędów i wyprowadzanie informacji (314)
  • Funkcja Magic SysRq Key (315)
  • Saga debugera jądra (315)
    • gdb (316)
    • kgdb (317)
    • kdb (318)
  • Stymulowanie i sondowanie systemu (318)
    • Uzależnianie wykonania kodu od identyfikatora UID (318)
    • Korzystanie ze zmiennych warunkowych (319)
    • Korzystanie ze statystyk (319)
    • Ograniczanie częstotliwości komunikatów diagnostycznych (319)
  • Szukanie winowajcy - wyszukiwanie binarne (321)
  • Koledzy - kiedy wszystko inne zawiedzie (322)

Rozdział 16. Przenośność (323)

  • Historia przenośności systemu Linux (325)
  • Rozmiar słowa i typy danych (326)
    • Typy nieprzejrzyste (328)
    • Typy specjalne (329)
    • Typy o zadanych rozmiarach (329)
    • Znak typu char (330)
  • Wyrównanie danych (331)
    • Unikanie problemów wyrównywania (331)
    • Wyrównanie typów niestandardowych (332)
    • Dopełnienie struktury (332)
  • Wzajemny porządek bajtów (333)
    • Typy wzajemnego porządku bajtów - rys historyczny (335)
    • Wzajemny porządek bajtów w jądrze (335)
  • Pomiar upływu czasu (336)
  • Rozmiar strony (336)
  • Kolejność wykonywania instrukcji (337)
  • Tryb SMP, wywłaszczanie jądra i pamięć wysoka (338)
  • Przenośność to wyzwanie (338)

Rozdział 17. Łaty, haking i społeczność (339)

  • Społeczność (339)
  • Obowiązujący styl kodowania (340)
    • Wcięcia (341)
    • Nawiasy klamrowe (341)
    • Nazewnictwo (342)
    • Funkcje (342)
    • Komentarze (343)
    • Definicje typów (344)
    • Korzystanie z zastanego (344)
    • Unikanie definicji ifdef w kodzie źródłowym (344)
    • Inicjalizacja struktur (345)
    • Poprawianie złego stylu (345)
  • Łańcuch poleceń (346)
  • Przesyłanie raportów o błędach (346)
  • Generowanie łat (347)
  • Rozsyłanie łat (348)

Dodatek A Korzystanie z list (351)

  • Listy cykliczne (351)
    • Poruszanie się pomiędzy elementami listy (352)
  • Implementacja listy w jądrze Linuksa (353)
    • Struktura listy (353)
  • Manipulowanie listami (354)
  • Przeglądanie list (356)

Dodatek B Interfejs procesora (359)

  • Nowy interfejs procesora (360)
    • Statyczne dane procesora (360)
    • Dynamiczne dane procesora (361)
  • Po co korzystać z danych procesora? (362)

Dodatek C Generator liczb losowych jądra (365)

  • Projekt i implementacja puli entropii (366)
    • Problem rozruchu programu (368)
  • Interfejs wejściowy puli entropii (368)
  • Interfejs wyjściowy puli entropii (369)

Dodatek D Złożoność obliczeniowa (371)

  • Algorytmy (371)
  • Zapis złożoności O(x) (372)
  • Notacja duże theta (372)
  • Co z tego wynika? (373)
  • Pułapki złożoności czasowej (373)

Dodatek E Bibliografia i lektury dodatkowe (375)

  • Książki o projektowaniu systemów operacyjnych (375)
  • Książki o jądrze systemu Unix (376)
  • Książki o jądrze systemu Linux (377)
  • Książki o jądrach innych systemów operacyjnych (377)
  • Książki o interfejsie programowym Uniksa (377)
  • Inne książki (378)
  • Witryny WWW (378)

Skorowidz (381)
 

openSuSE Linux

openSuSE jest dystrybucją Linuksa sponsorowaną przez firmę Novell. Jest to Linux doskonale sprawdzający się jako system serwerowy, choć głównym zamierzeniem jego twórców było stworzenie Linuksa typu desktop. OpenSuSE Linux jest doskonałą alternatywą dla systemów Microsoft. Zawiera dopracowane graficzne narzędzia konfiguracyjne YaST i SaX2. Doskonale nadaje się dla początkujących użytkowników Linuksa.

Mandriva Linux

Mandriva Linux jest jedną z najpopularniejszych dystrybucji ogólnego użytku ostatnich lat. Dzięki swojej innowacyjności zdobyla uznanie zarówno początkujących jak i zaawansowanych użytkowników Linuksa. W kolejnych, wydawanych cyklicznie w odstępach półrocznych wersjach Mandriva Linux jest liderem we wprowadzaniu nowych narzędzi i funkcjonalności, niedostępnych jeszcze w innych dystrybucjach Linuksa.

Slackware Linux

Slackware Linux jest jedną z najstarszych dystrybucji Linuksa, rozwijaną aktywnie aż do chwili obecnej. Pierwsza wersja Slackware Linux została wydana w lipcu 1993 roku jako dystrybucja dla zaawansowanych użytkowników. Do chwili obecnej, jako jedna z niewielu dystrybucji, Slackware Linux wykorzystuje podczas instalacji tekstową wersję instalatora, przez co uznawana jest niesłusznie za trudniejszą w instalacji niż inne popularne dystrybucje.

Copyright 2003-2011 PHU Altkomp

stat4u