Jądro Linuksa. Przewodnik programisty
Autor: Robert Love
Stron: 504
Ksiazka drukowana Druk (oprawa: miękka)
Tytuł oryginału: Linux Kernel Development (3rd Edition)
Tłumaczenie: Przemysław Szeremiota
ISBN Książki drukowanej: 978-83-[zasłonięte]-4273-1, 978[zasłonięte][zasłonięte]46427
Data wydania książki drukowanej: 2[zasłonięte]014-02
Format: 170x230
Numer z katalogu: 17927
Wnieś swój wkład w rozwój Linuksa!
Jądro systemu Linux to jedno z największych osiągnięć otwartej społeczności programistów. Projekt ten, zainicjowany przez Linusa Torvaldsa, światło dzienne ujrzał w 1991 roku. Od tamtego czasu coraz więcej ochotników wspiera jego doskonalenie. Pozwoliło to na wprowadzenie do jądra wielu nowatorskich funkcji i wyznaczenie trendów w rozwoju współczesnego oprogramowania oraz systemów operacyjnych. Prace nad tym gigantycznym projektem przyczyniły się też do powstania mnóstwa innych produktów - w tym zdobywającego ogromną popularność rozproszonego systemu kontroli wersji Git.
Tak dynamiczny rozwój ma jeden niedobry skutek uboczny. Początkujący programiści mają problem z ogarnięciem ogromu projektu i poznaniem jego architektury. Ten długotrwały proces zdecydowanie skróci przewodnik, który właśnie trzymasz w rękach. Przeprowadzi Cię on przez tajemnice systemu. Dowiesz się, jak pobrać kod źródłowy jądra, jak go skonfigurować oraz skompilować. W kolejnych rozdziałach poznasz kluczowe mechanizmy: zarządzania procesami, szeregowania zadań, wywołań systemowych oraz przerwań. Ponadto nauczysz się korzystać z urządzeń blokowych, pamięci podręcznej, sterowników i modułów. Ta książka jest obowiązkową lekturą dla wszystkich programistów, którzy chcą mieć swój wkład w rozwój projektu Torvaldsa. Sprawdzi się ona również w rękach osób, które po prostu chcą zrozumieć, jak działa ten niezwykły system.
Dzięki tej książce:
pobierzesz, skonfigurujesz i skompilujesz źródła jądra
zrozumiesz zasady zarządzania procesami
poznasz struktury danych jądra
wykorzystasz wirtualne systemy plików
zyskasz możliwość samodzielnego rozwijania jądra system Linux
Przekonaj się, jak działa jądro Linuksa!
Przedmowa (17)
Wstęp (19)
Rozdział 1. Jądro systemu Linux - wprowadzenie (25)
Historia Uniksa (25)
Wprowadzenie do systemu Linux (27)
Przegląd systemów operacyjnych (29)
Jądro Linuksa a jądro klasycznego systemu uniksowego (31)
Oznaczenia wersji jądra Linuksa (34)
Społeczność programistów jądra Linuksa (35)
Zanim zaczniemy (36)
Rozdział 2. Linux - zaczynamy (37)
Kod źródłowy jądra (37)
Git (37)
Instalowanie źródeł jądra z archiwum (38)
Aplikowanie łat (39)
Struktura katalogów kodu źródłowego jądra (39)
Kompilowanie jądra (40)
Konfigurowanie jądra (41)
Minimalizacja szumu podczas kompilacji (43)
Kompilacja na wielu frontach (43)
Instalowanie nowego jądra (44)
Odmienność jądra (45)
Brak implementacji i nagłówków biblioteki standardowej C (45)
GNU C (47)
Brak mechanizmu ochrony pamięci (49)
Niemożność (łatwego) korzystania z operacji zmiennoprzecinkowych (50)
Ograniczony co do rozmiaru (i stały) stos (50)
Synchronizacja i współbieżność (50)
Znaczenie przenośności (51)
Podsumowanie (51)
Rozdział 3. Zarządzanie procesami (53)
Proces (53)
Deskryptor procesu i struktura zadania (55)
Przydział deskryptora procesu (55)
Przechowywanie deskryptora procesu (57)
Stan procesu (58)
Manipulowanie bieżącym stanem procesu (59)
Kontekst procesu (60)
Drzewo procesów (60)
Tworzenie procesu (62)
Kopiowanie przy zapisie (62)
Rozwidlanie procesu (63)
Wywołanie vfork() (64)
Wątki w systemie Linux (65)
Tworzenie wątków (66)
Wątki jądra (67)
Zakończenie procesu (68)
Usuwanie deskryptora procesu (70)
Problem zadań osieroconych (71)
Podsumowanie (73)
Rozdział 4. Szeregowanie zadań (75)
Wielozadaniowość (75)
Planista zadań w Linuksie (77)
Strategia postępowania (77)
Procesy ograniczone wejściem-wyjściem a procesy ograniczone procesorem (78)
Priorytet procesu (79)
Kwant czasu procesora (80)
Strategia szeregowania w działaniu (81)
Algorytm szeregowania zadań w Linuksie (82)
Klasy szeregowania (82)
Szeregowanie procesów w systemach klasy Unix (82)
Sprawiedliwe szeregowanie zadań (85)
Implementacja szeregowania zadań w Linuksie (87)
Zliczanie czasu wykonania (87)
Wybór procesu (89)
Punkt wejścia do planisty CFS (94)
Zawieszanie i wybudzanie procesów (95)
Wywłaszczanie i przełączanie kontekstu (99)
Wywłaszczanie procesu użytkownika (100)
Wywłaszczenie jądra (101)
Szeregowanie czasu rzeczywistego (102)
Wywołania systemowe związane z szeregowaniem (103)
Wywołania wpływające na strategię szeregowania i wartości priorytetów (104)
Wywołania systemowe sterujące kojarzeniem procesów z procesorami (105)
Odstąpienie procesora (105)
Podsumowanie (106)
Rozdział 5. Wywołania systemowe (107)
Komunikacja z jądrem systemu (107)
API, POSIX i biblioteka C (108)
Wywołania systemowe (109)
Numery wywołań systemowych (111)
Wydajność wywołania systemowego (111)
Procedura obsługi wywołań systemowych (111)
Oznaczanie właściwego wywołania systemowego (112)
Przekazywanie argumentów (113)
Implementacja wywołania systemowego (113)
Implementowanie wywołań systemowych (114)
Weryfikacja argumentów (114)
Kontekst wywołania systemowego (118)
Wiązanie wywołania systemowego (119)
Inicjowanie wywołania systemowego z przestrzeni użytkownika (120)
Sześć powodów, aby nie implementować wywołań systemowych (121)
Podsumowanie (122)
Rozdział 6. Struktury danych jądra (123)
Listy (123)
Listy jedno- i dwukierunkowe (124)
Listy cykliczne (124)
Implementacja list w jądrze Linuksa (126)
Operacje na listach (128)
Przeglądanie list (131)
Inne operacje na listach (134)
Kolejki (135)
kfifo (135)
Tworzenie kolejki (136)
Zakolejkowanie (137)
Wyciąganie danych (137)
Określanie rozmiaru kolejki (137)
Zerowanie i usuwanie kolejki (138)
Przykład użycia kolejki kfifo (138)
Mapy (139)
Inicjalizowanie mapy idr (140)
Przydział nowego identyfikatora UID (140)
Odwzorowanie UID na wskaźnik (141)
Usuwanie UID (142)
Usuwanie idr (142)
Drzewa binarne (143)
Drzewa BST (143)
Zrównoważone drzewa BST (144)
Drzewa czerwono-czarne (145)
rbtree (146)
Kiedy i jakiej struktury użyć? (148)
Złożoność obliczeniowa (149)
Algorytmy (149)
Notacja O (149)
Notacja theta (150)
Złożoność czasowa (150)
Podsumowanie (151)
Rozdział 7. Przerwania i procedury obsługi przerwań (153)
Przerwania (154)
Procedury obsługi przerwań (155)
Połówki górne i dolne (156)
Rejestrowanie procedury obsługi przerwania (157)
Znaczniki procedury obsługi przerwań (158)
Przykładowe przerwanie (159)
Zwalnianie procedury obsługi przerwania (160)
Tworzenie procedury obsługi przerwań (160)
Procedury obsługi przerwań współużytkowanych (162)
Prawdziwa procedura obsługi przerwania (163)
Kontekst przerwania (165)
Implementacja obsługi przerwań (166)
/proc/interrupts (168)
Kontrola przerwań (169)
Wyłączanie i włączanie przerwań (170)
Blokowanie konkretnej linii przerwania (172)
Stan systemu przerwań (173)
Podsumowanie (174)
Rozdział 8. Dolne połówki i czynności odroczone (175)
Połówki dolne (176)
Po co dolne połówki? (177)
Świat dolnych połówek (178)
Przerwania programowe (181)
Implementacja przerwań programowych (181)
Korzystanie z przerwań programowych (183)
Tasklety (186)
Implementacja taskletów (186)
Korzystanie z taskletów (189)
Wątek jądra ksoftirqd (191)
Dawny mechanizm BH (193)
Kolejki prac (194)
Implementacja kolejek prac (195)
Korzystanie z kolejek prac (199)
Dawny mechanizm kolejkowania zadań (201)
Jak wybrać implementację dolnej połówki? (202)
Blokowanie pomiędzy dolnymi połówkami (204)
Wyłączanie dolnych połówek (204)
Podsumowanie (206)
Rozdział 9. Wprowadzenie do synchronizacji jądra (207)
Sekcje krytyczne i przeplot operacji (208)
Po co ta ochrona? (208)
Zmienna globalna (210)
Blokowanie (211)
Źródła współbieżności (213)
Co wymaga zabezpieczania? (215)
Zakleszczenia (216)
Rywalizacja a skalowalność (218)
Podsumowanie (220)
Rozdział 10. Metody synchronizacji jądra (221)
Operacje niepodzielne (221)
Niepodzielne operacje na liczbach całkowitych (222)
64-bitowe operacje niepodzielne (226)
Niepodzielne operacje bitowe (228)
Rygle pętlowe (230)
Interfejs rygli pętlowych (231)
Inne metody blokowania ryglami pętlowymi (234)
Rygle pętlowe a dolne połówki (234)
Rygle pętlowe R-W (235)
Semafory (238)
Semafory binarne i zliczające (239)
Tworzenie i inicjalizowanie semaforów (240)
Korzystanie z semaforów (240)
Semafory R-W (241)
Muteksy (243)
Muteksy czy semafory? (245)
Muteksy czy rygle pętlowe? (245)
Zmienne sygnałowe (245)
Blokada BKL (Big Kernel Lock) (246)
Blokady sekwencyjne (247)
Blokowanie wywłaszczania (249)
Bariery pamięciowe (251)
Podsumowanie (255)
Rozdział 11. Liczniki i zarządzanie czasem (257)
Czas z punktu widzenia jądra (258)
Częstotliwość taktowania - HZ (259)
Optymalna wartość HZ (260)
Zalety wysokich wartości HZ (261)
Wady wysokich wartości HZ (262)
Chwilki (263)
Wewnętrzna reprezentacja zmiennej jiffies (264)
Zawijanie zmiennej jiffies (266)
HZ a przestrzeń użytkownika (267)
Zegary i liczniki sprzętowe (268)
Zegar czasu rzeczywistego (268)
Zegar systemowy (269)
Procedura obsługi przerwania zegarowego (269)
Data i godzina (272)
Liczniki (274)
Korzystanie z liczników (275)
Liczniki i sytuacje hazardowe (277)
Implementacja licznika (277)
Opóźnianie wykonania (278)
Oczekiwanie w pętli aktywnej (278)
Krótkie opóźnienia (280)
Funkcja schedule_timeout() (281)
Implementacja funkcji schedule_timeout() (282)
Podsumowanie (284)
Rozdział 12. Zarządzanie pamięcią (285)
Strony (285)
Strefy (287)
Pozyskiwanie stron pamięci (290)
Pozyskiwanie czystych stron pamięci (291)
Zwalnianie stron (291)
Funkcja kmalloc() (292)
Znaczniki gfp_mask (293)
Funkcja kfree() (298)
Funkcja vmalloc() (299)
Alokator plastrowy (301)
Zadania alokatora plastrowego (302)
Interfejs alokatora plastrowego (305)
Przydział z pamięci podręcznej (307)
Statyczne przydziały na stosie (309)
Jednostronicowy stos procesów jądra (309)
Ostrożnie ze stosem (310)
Odwzorowanie pamięci wysokiej (310)
Odwzorowanie trwałe (311)
Odwzorowania czasowe (311)
Przydziały lokalne względem procesora (312)
Interfejs percpu (313)
Statyczne dane lokalne względem procesora (313)
Dynamiczne dane lokalne względem procesora (314)
Przydatność danych lokalnych względem procesora (315)
Wybór metody przydziału pamięci w kodzie jądra (316)
Podsumowanie (317)
Rozdział 13. Wirtualny system plików (319)
Wspólny interfejs systemu plików (320)
Warstwa abstrakcji systemu plików (320)
Uniksowy system plików (322)
Obiekty VFS i ich struktury danych (323)
Obiekt bloku głównego (325)
Operacje bloku głównego (326)
Obiekt i-węzła (329)
Operacje i-węzła (331)
Obiekt wpisu katalogowego (334)
Stan wpisu katalogowego (335)
Bufor wpisów katalogowych (336)
Operacje na wpisach katalogowych (337)
Obiekt pliku (339)
Operacje na plikach (340)
Struktury danych systemu plików (343)
Struktury danych procesu (345)
Podsumowanie (347)
Rozdział 14. Blokowe urządzenia wejścia-wyjścia (349)
Anatomia urządzenia blokowego (350)
Bufory i nagłówki buforów (351)
Struktura bio (354)
Wektory wejścia-wyjścia (355)
Stare a nowe (357)
Kolejki zleceń (357)
Zawiadywanie operacjami wejścia-wyjścia (358)
Zadania planisty operacji wejścia-wyjścia (359)
Winda Linusa (360)
Terminowy planista operacji wejścia-wyjścia (361)
Przewidujący planista operacji wejścia-wyjścia (363)
Sprawiedliwy planista kolejkowania operacji wejścia-wyjścia (364)
Nieingerujący planista operacji wejścia-wyjścia (365)
Wybór planisty operacji wejścia-wyjścia (366)
Podsumowanie (366)
Rozdział 15. Przestrzeń adresowa procesu (367)
Przestrzenie adresowe (367)
Deskryptor pamięci (369)
Przydział deskryptora pamięci (371)
Zwalnianie deskryptora pamięci (371)
Struktura mm_struct i wątki jądra (372)
Obszary pamięci wirtualnej (372)
Znaczniki VMA (374)
Operacje VMA (375)
Obszary pamięci na listach i w drzewach (376)
Obszary pamięci w praktyce (377)
Manipulowanie obszarami pamięci (379)
Funkcja find_vma() (379)
Funkcja find_vma_prev() (381)
Funkcja find_vma_intersection() (381)
Tworzenie interwału adresów - wywołania mmap() i do_mmap() (381)
Usuwanie interwału adresów - wywołania munmap() i do_munmap() (383)
Tablice stron (384)
Podsumowanie (386)
Rozdział 16. Pamięć podręczna stron i opóźniony zapis stron w tle (387)
Modele pamięci podręcznych (387)
Buforowanie zapisów (388)
Eksmisja z pamięci podręcznej (389)
Pamięć podręczna stron w Linuksie (391)
Obiekt address_space (391)
Operacje na obiektach address_space (392)
Drzewo pozycyjne (395)
Tablica skrótów stron (395)
Pamięć podręczna buforów (396)
Wątki zapisu w tle (396)
Tryb laptopowy (398)
Rys historyczny - bdflush, kupdated i pdflush (399)
Eliminowanie obciążenia operacjami wejścia-wyjścia (400)
Podsumowanie (401)
Rozdział 17. Sterowniki i moduły (403)
Typy urządzeń (403)
Moduły (404)
Hello, world! (405)
Kompilowanie modułów (406)
Instalowanie modułów (409)
Generowanie zależności międzymodułowych (409)
Ładowanie modułów (410)
Zarządzanie opcjami konfiguracji jądra (411)
Parametry modułów (413)
Symbole eksportowane (415)
Model sterowników (416)
Obiekty jądra (417)
Typy obiektów jądra (418)
Grupy obiektów jądra (419)
Powiązania pomiędzy obiektami, typami i grupami obiektów jądra (419)
Zarządzanie i operowanie obiektami jądra (420)
Zliczanie odwołań (421)
System plików sysfs (423)
Dodawanie i usuwanie obiektów jądra w sysfs (426)
Dodawanie plików do sysfs (427)
Kernel Event Layer (430)
Podsumowanie (431)
Rozdział 18. Diagnostyka błędów jądra (433)
Od czego zacząć? (433)
Błędy w jądrze (434)
Diagnostyka komunikatami (435)
Niezawodność printk() (435)
Poziomy diagnostyczne (436)
Bufor komunikatów (437)
Demony syslogd i klogd (438)
printf(), printk() - łatwo o pomyłkę (438)
Błąd oops (438)
Polecenie ksymoops (440)
kallsyms (441)
Opcje diagnostyczne jądra (441)
Asercje i wypisywanie informacji o błędach (442)
Funkcja Magic SysRq Key (443)
Saga debugera jądra (444)
gdb (445)
kgdb (446)
Stymulowanie i sondowanie systemu (446)
Uzależnianie wykonania kodu od identyfikatora UID (446)
Korzystanie ze zmiennych warunkowych (447)
Korzystanie ze statystyk (447)
Ograniczanie częstotliwości i liczby komunikatów diagnostycznych (448)
Szukanie winowajcy - wyszukiwanie binarne (449)
Binarne wyszukiwanie wersji za pomocą Gita (450)
Koledzy - kiedy wszystko inne zawiedzie (451)
Podsumowanie (451)
Rozdział 19. Przenośność (453)
Przenośne systemy operacyjne (453)
Historia przenośności systemu Linux (455)
Rozmiar słowa i typy danych (456)
Typy nieprzejrzyste (459)
Typy specjalne (459)
Typy o zadanych rozmiarach (460)
Znak typu char (461)
Wyrównanie danych (462)
Unikanie problemów wyrównywania (462)
Wyrównanie typów niestandardowych (463)
Dopełnienie struktury (463)
Wzajemny porządek bajtów (465)
Pomiar upływu czasu (467)
Rozmiar strony (468)
Kolejność wykonywania instrukcji (469)
Tryb SMP, wywłaszczanie jądra i pamięć wysoka (469)
Podsumowanie (470)
Rozdział 20. Kodowanie, łaty i społeczność (471)
Społeczność (471)
Obowiązujący styl kodowania (472)
Wcięcia (472)
Instrukcje switch (473)
Odstępy (473)
Nawiasy klamrowe (475)
Długość wiersza kodu (476)
Nazewnictwo (476)
Funkcje (477)
Komentarze (477)
Definicje typów (478)
Korzystanie z gotowców (478)
Unikanie definicji ifdef w ciele funkcji (478)
Inicjalizacja struktur (479)
Poprawianie złego stylu (479)
Łańcuch poleceń (480)
Przesyłanie raportów o błędach (480)
Łaty (481)
Generowanie łat (481)
Generowanie łat za pomocą Gita (482)
Rozsyłanie łat (483)
Podsumowanie (484)
Dodatek A. Bibliografia (485)
Książki o projektowaniu systemów operacyjnych (485)
Książki o jądrze systemu Unix (486)
Książki o jądrze systemu Linux (486)
Książki o jądrach innych systemów operacyjnych (487)
Książki o interfejsie programowym Uniksa (487)
Książki o programowaniu w języku C (487)
Inne książki (488)
Witryny WWW (488)
Skorowidz (489)