Jak zacząć współtworzyć jądro Linuksa: pierwszy patch

Jądro Linuksa jest jednym z największych projektów tworzonych wspólnie przez programistów z całego świata, a jego rozwój opiera się na jasno opisanych zasadach. Dla osoby, która chce dołączyć do społeczności, największą barierą nie jest zwykle język programowania, lecz nieznajomość procesu: kto ocenia zmiany, jak się je przesyła i dlaczego odpowiedź nie przychodzi od razu. Dokumentacja jądra, projekt KernelNewbies i praktyka maintainerów układają się w spójną ścieżkę od pierwszej lektury do pierwszej zaakceptowanej poprawki. Wiedza o tej ścieżce pozwala uniknąć najczęstszych błędów, takich jak wysyłanie patchy w załącznikach, pomijanie właściwych adresatów czy brak podpisu w opisie zmiany. Przewodnik zestawia wymagania formalne z praktyką pracy i pokazuje, od czego zacząć.

Programista przy kodzie źródłowym jądra Linuksa

Jądro Linuksa jako projekt wspólny

Patch wysłany na listę dyskusyjną nie trafia od razu do kodu. Najpierw czyta go maintainer odpowiedniego podsystemu, potem recenzenci, a odpowiedź według dokumentacji jądra przychodzi zwykle po dwóch–trzech tygodniach. Ten rytm pracy wynika ze skali projektu: dokumentacja podaje, że jądro liczy ponad 8 mln linii kodu, a w każdym wydaniu uczestniczy ponad 1000 programistów z ponad 100 różnych firm. Proces musi więc zapewnić porządek i odpowiedzialność tam, gdzie żadna pojedyncza osoba nie jest w stanie przejrzeć całości.

Dla nowego uczestnika wynikają z tego dwie praktyczne konsekwencje. Pierwsza dotyczy licencji: wkład musi być zgodny z GNU General Public License w wersji 2, a dopuszczalna jest także trzyklauzulowa licencja BSD. Druga dotyczy praw autorskich: dokumentacja zaznacza, że cesja praw autorskich nie jest wymagana, ale każdy patch musi zawierać podpis autora w postaci wiersza Signed-off-by. Sprawy formalne są więc proste, a trudność leży w nauczeniu się sposobu pracy społeczności. Dokumentacja otwarcie ostrzega, że społeczność wykształciła własne zasady działania, które różnią się od metod stosowanych w projektach zamkniętych, a programiści, którzy ich nie rozumieją lub nie szanują, napotykają trudności. Znajomość tych zasad jest więc równie ważna jak umiejętność programowania.

Wkład w jądro kontra kod poza drzewem

Początkujący programista staje przed wyborem: oddać zmianę do głównej gałęzi (mainline) albo utrzymywać ją osobno jako kod spoza drzewa (out-of-tree). Dokumentacja jądra opisuje obie ścieżki wprost. Kod włączony do mainline trafia automatycznie do każdej dystrybucji, która dany element włącza, a jego utrzymanie jest tańsze dzięki zasadom stabilności interfejsów. Kod spoza drzewa wymaga według dokumentacji stałej pracy, ma kłopoty z obsługą przez dystrybucje i trudniej utrzymać w nim jakość.

Za wkładem w mainline przemawiają też argumenty techniczne. Recenzja społeczności wychwytuje błędy, których autor nie widzi, a włączenie zmiany daje wpływ na kierunek rozwoju jądra i zapobiega powstawaniu konkurencyjnych implementacji tego samego rozwiązania. Koszt tej ścieżki to czas i cierpliwość, ponieważ każdy patch przechodzi przez recenzję i wymaga poprawek.

Rachunek jest więc prosty. Gdy zmiana ma być używana szeroko i długo, opłaca się ją oddać do mainline, bo wtedy koszt jej utrzymania dzieli cała społeczność, a nie jeden zespół. Gdy służy wyłącznie jednemu wdrożeniu, można ją utrzymywać samodzielnie, trzeba jednak liczyć się z kosztem synchronizacji po każdym nowym wydaniu jądra.

Cykl wydań wyznacza tempo pracy

Jądro rozwija się w modelu czasowym. Dokumentacja podaje, że nowe wydanie główne pojawia się co dwa do trzech miesięcy, a okno włączania zmian (merge window) trwa około dwóch tygodni, w czasie których do kodu trafia mniej więcej 1000 zmian dziennie. Po jego zamknięciu wychodzi wersja rc1, a przez kolejne sześć do dziesięciu tygodni przyjmowane są wyłącznie poprawki błędów. Wydanie bywa poprzedzone kandydatami od rc6 do rc9, zanim jądro zostanie uznane za wystarczająco stabilne.

Typowe wydanie zawiera według dokumentacji około 13 tys. zmian (changesets), a w ciągu roku nad jądrem pracuje rząd 2000 programistów. Liczby te pochodzą z opracowania, które jest starsze niż obecne wersje, więc traktuje się je jako rząd wielkości, a nie dokładną statystykę. Wniosek praktyczny pozostaje ten sam: patch wysłany w oknie włączania konkuruje o uwagę z tysiącami innych, dlatego lepiej zgłaszać zmiany wcześniej i dbać o ich jakość.

Termin premiery wydania nie jest ustalany z góry. Dokumentacja cytuje Andrew Mortona, według którego nikt nie wie, kiedy ukaże się nowe jądro, ponieważ jest ono wydawane według postrzeganego stanu błędów, a nie według wcześniej przyjętego harmonogramu. Po zamknięciu okna włączania kandydaci do wydania ukazują się mniej więcej co tydzień, a cała faza stabilizacji trwa zwykle około sześciu do dziesięciu tygodni.

Rola maintainerów i drzewa linux-next

Maintainerzy podsystemów działają jak strażnicy poszczególnych części kodu: decydują, które patche trafią do mainline. Lista maintainerów, ich list dyskusyjnych i repozytoriów znajduje się w pliku MAINTAINERS. Zmiany powinny trafić do drzewa linux-next jeszcze przed otwarciem okna włączania, ponieważ pozwala ono wykryć konflikty między podsystemami, zanim kod wejdzie do głównej gałęzi.

Pierwszy patch krok po kroku

Ścieżkę wejścia opisują dokumentacja jądra i projekt KernelNewbies. Na początek najlepiej wybrać drzewo staging, które zawiera sterowniki wymagające porządkowania. Projekt Kernel Janitors zbiera relatywnie proste problemy do rozwiązania, co pozwala poznać zasady wysyłania zmian bez ryzyka zepsucia kluczowych mechanizmów. Przy pierwszym patchu zaleca się wybór jednej zmiany, na przykład jednego ostrzeżenia lub uwagi narzędzia checkpatch.

Ograniczenie się do jednej zmiany ma uzasadnienie praktyczne: małą poprawkę recenzent może ocenić w kilka minut, a autorowi łatwiej wprowadzić uwagi i przygotować kolejną wersję bez konfliktów z innymi zmianami. Kolejność działań wygląda następująco:

  1. Skonfiguruj git, podając imię i adres e-mail zgodny z tym, z którego będziesz wysyłać pocztę.
  2. Uruchom skrypt `scripts/checkpatch.pl` na wybranym pliku i wybierz jedną uwagę do poprawienia.
  3. Zbuduj zmodyfikowane jądro i sprawdź zmianę, na przykład ładując moduł sterownika.
  4. Zatwierdź zmianę z opisem zaczynającym się od przedrostka podsystemu, a następnie wygeneruj patch poleceniem `git format-patch`.
  5. Ustal adresatów skryptem `scripts/get_maintainer.pl` i wyślij patch w treści wiadomości, nie jako załącznik, na przykład przez `git send-email`.

Przed wysłaniem warto dołączyć informację o bazie, względem której przygotowano patch. Pozwala na to polecenie `git format-patch --base=auto`: recenzenci i systemy ciągłej integracji mogą dzięki temu zastosować zmianę bez konfliktów. Odpowiedzi na uwagi recenzentów powinny być rzeczowe i uprzejme, a każda uwaga zostać uwzględniona albo uzasadnienie jej odrzucenia przedstawione na liście.

Co powinien zawierać opis zmiany

Dokumentacja wymaga krótkiego tematu, nieprzekraczającego około 70–75 znaków, oraz opisu problemu i rozwiązania z technicznymi szczegółami. Temat powinien zawierać przedrostek podsystemu, a przy wysyłce w tytule wiadomości umieszcza się oznaczenie [PATCH]. Przy kolejnych wersjach numeruje się je (v2, v3), a opis zmian względem poprzedniej wersji umieszcza pod linią `---`, żeby nie trafił do historii jądra.

Kod, który trafi do jądra, znajdzie się automatycznie w każdej dystrybucji włączającej dany element, a kod spoza drzewa trzeba utrzymywać samodzielnie.

Podpis Signed-off-by jako gwarancja pochodzenia

Wiersz Signed-off-by to nie formalność, lecz oświadczenie prawne zapisane w Developer's Certificate of Origin w wersji 1.1. Oznacza ono, że autor spełnia jeden z trzech warunków: sam napisał wkład i ma prawo przekazać go na licencji projektu, oparł go na wcześniejszej pracy objętej odpowiednią licencją albo otrzymał go od osoby, która potwierdziła pochodzenie kodu, i nie modyfikował go. Autor przyjmuje przy tym do wiadomości, że wkład razem z danymi osobowymi, które z nim przekazał, zostanie trwale zapisany i może być redystrybuowany.

Dzięki temu mechanizmowi historia każdego patcha ma łańcuch odpowiedzialności: widać, kto napisał kod i którzy maintainerzy przekazywali go dalej. Dla nowego uczestnika wniosek jest praktyczny: do projektu wolno przesyłać wyłącznie kod, do którego ma się prawa, a wszelkie wątpliwości licencyjne trzeba wyjaśnić przed wysłaniem. Dokumentacja zaznacza przy tym, że pytania prawne należy kierować do prawnika, a nie na listy dyskusyjne, które nie są miejscem na porady tego rodzaju.

Społeczność Linuksa w praktyce: pierwszy tydzień pracy

Pierwszy tydzień warto zaplanować jako serię małych kroków, a nie jedno duże zadanie. W pierwszych dniach przeczytaj trzy dokumenty wskazane przez dokumentację jądra: README z podręcznika administratora, zasady stylu kodowania i instrukcję wysyłania patchy. Następnie zapoznaj się z kodem przy użyciu narzędzia Elixir (elixir.bootlin.com), które indeksuje źródła jądra i pozwala śledzić odwołania między plikami. Potem dołącz do listy dyskusyjnej KernelNewbies, na której zadaje się podstawowe pytania.

Dopiero po tym przygotowaniu wybierz jeden plik ze sterownikiem w drzewie staging i uruchom na nim checkpatch. Dokumentacja zaleca, by przed zmianą kodu dokładnie go przestudiować, zamiast poprawiać fragmenty bez zrozumienia ich roli. Pierwszy patch nie musi być imponujący. Wystarczy, że będzie poprawny formalnie, dobrze opisany i wysłany do właściwych osób. Pierwszy realny krok na dziś: otwórz plik MAINTAINERS i sprawdź, kto odpowiada za podsystem, który Cię interesuje.

Najczęściej zadawane pytania o wkład w jądro Linuksa

Czy trzeba oddawać prawa autorskie do kodu?

Nie. Dokumentacja jądra wyraźnie zaznacza, że cesja praw autorskich nie jest wymagana. Wkład musi być jednak zgodny z GPLv2, a dopuszczalna jest również trzyklauzulowa licencja BSD. Autor zachowuje prawa do swojego kodu, a w zamian zobowiązuje się do podpisania patcha wierszem Signed-off-by.

Jak długo czeka się na odpowiedź na patch?

Według dokumentacji pierwsze uwagi zwykle pojawiają się po dwóch–trzech tygodniach. Przed ponownym wysłaniem tej samej zmiany należy odczekać co najmniej tydzień, a niezmienioną wiadomość oznacza się dopiskiem RESEND. Gdy poprawiasz patch po recenzji, odpowiedz na wszystkie uwagi i opisz zmiany względem poprzedniej wersji.

Gdzie szukać prostych zadań na początek?

Dokumentacja wskazuje projekt Kernel Janitors, który zbiera stosunkowo proste problemy do rozwiązania, oraz portal KernelNewbies z listą dyskusyjną i kanałem IRC dla początkujących. Do poznawania kodu przydaje się indeksujące źródła narzędzie Elixir. Dobrym polem treningowym jest też drzewo staging ze sterownikami wymagającymi uporządkowania.

Jak zachowywać się na liście dyskusyjnej?

Zasady są konkretne: najpierw przeszukaj archiwum, zanim zadasz pytanie, nie usuwaj osób z kopii bez powodu, zachowuj wiersze atrybucji i wysyłaj wiadomości jako zwykły tekst. Patche wysyła się w treści listu, nigdy w załączniku. Zasady te ułatwiają recenzję, bo każdy uczestnik widzi pełną dyskusję i może komentować kod bezpośrednio. Listy dyskusyjne subskrybuje się przez serwis subspace.kernel.org, a przed pierwszym wpisem warto przejrzeć archiwum, ponieważ podobne pytanie bardzo często zostało już omówione.

Do czego służy plik MAINTAINERS?

To lista podsystemów jądra wraz z maintainerami, powiązanymi listami dyskusyjnymi i lokalizacją repozytoriów. Pozwala ustalić, do kogo wysłać patch. Skrypt `scripts/get_maintainer.pl` przeszukuje ten plik i podpowiada adresatów dla konkretnej zmiany, co dokumentacja traktuje jako obowiązek: do patcha należy zawsze dołączyć właściwych maintainerów i listy.

Partner Strony: e-produkcja.pl