Linux Kernel. Przewodnik programisty - Helion
Tłumaczenie: Przemysław Szeremiota
ISBN: 83-7361-439-7
stron: 400, Format: B5, okładka: miękka
Data wydania: 2004-04-20
Księgarnia: Helion
Cena książki: 49,90 zł
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.
Osoby które kupowały "Linux Kernel. Przewodnik programisty", wybierały także:
- Superinteligencja. Scenariusze, strategie, zagro 66,67 zł, (14,00 zł -79%)
- Poradnik design thinking - czyli jak wykorzysta 48,28 zł, (14,00 zł -71%)
- Kosymulacja. Elastyczne projektowanie i symulacja wielodomenowa 38,39 zł, (11,90 zł -69%)
- F# 4.0 dla zaawansowanych. Wydanie IV 96,45 zł, (29,90 zł -69%)
- Systemy reaktywne. Wzorce projektowe i ich stosowanie 65,31 zł, (20,90 zł -68%)
Spis treści
Linux Kernel. Przewodnik programisty -- 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)