Ostatnimi czasy rozgorzała na liście dyskusja na temat dodawania nowego podsystemu. Problem rozwiązano w niecodzienny sposób. Johan Hovold opublikował kod, który w celu wsparcia urządzeń GPS dodaje do jądra Linuksa podsystem GNSS (Global Navigation Satellite System), konieczny ze względu na to, że na rynku istnieje szerokie spektrum systemów wejścia/wyjścia wykorzystywanych przez te urządzenia. Niektóre opierają się na UART, komunikując się przez port szeregowy, podczas gdy twórcy innych decydują się na porty USB. Wykorzystywane są też i inne interfejsy. Johan chciałby utworzyć warstwę abstrakcji, tak aby kod użytkownika mógł współpracować z urządzeniami GPS bez względu na to, jakie wymagania posiada ich interfejs. Pomysł opiera się na stworzeniu nowego pliku w przestrzeni użytkownika: /dev/gnss0, z którego można skorzystać, aby kontrolować dowolne urządzenie GPS podłączone do działającego systemu.
Aby rozwiązanie zaczęło działać, Johan zaimplementował też sterowniki dla układów SiRFstar i U-blox GNSS.
Pavel Machek stwierdził, że nie jest to dobre rozwiązanie. Zauważył, że w zasadzie nie ma w nim kodu dla GNSS, a zamiast tego jest prosty podsystem zarządzania urządzeniami portu szeregowego, który nie będzie w stanie obsłużyć całej różnorodności urządzeń GPS. Powiedział: „Rozwiązanie to nie obsłuży na przykład Nokii N900, w której połączenie GPS realizowane jest przez Netlink”, czyli już istniejący w jądrze interfejs.
Johan odpowiedział, że cały sens warstwy abstrakcji polega na tym, że pozwala się przestrzeni użytkownika wykrywać urządzenia GPS bez potrzeby pisania własnego kodu do sprawdzania, czy są podłączone. Dlatego jest to rozwiązanie charakterystyczne dla GNSS. Powiedział, że najnowsza wersja łatki podaje typ odbiornika GNSS i posiada sterownik GNSS dla układów SiRFstar i U-blox. No koniec zauważył, że kod ten nie jest skierowany jedynie do urządzeń portu szeregowego, ponieważ działa również z innymi interfejsami.
Pavel w dalszym ciągu nie chciał się z tym zgodzić. Powiedział, że dokładnie te same funkcje, które wprowadza Johan, mogą być dodane do modemów AT (czyli modemów korzystających z zestawu poleceń Hayes AT). Zauważył, że polecenia AT również obejmują szeroki zakres interfejsów.
Pavel stwierdził, że jest wiele urządzeń GPS, takich jak Nokia N900, które nie będą działać z kodem Johana. Dobry podsystem GNSS powinien wspierać wszystkie urządzenia GPS. Oznajmił: „Myślę też, że powinniśmy skorzystać z twojego kodu w przypadku poleceń AT. Natomiast nazwy GNSS/GPS lepiej zachować na potrzeby przyszłej warstwy, która rzeczywiście dostarczy jednego interfejsu dla użytkownika”.
Johan bronił swojej łatki, mówiąc: „To kwestia znalezienia odpowiedniego poziomu abstrakcji. Przestrzeń użytkownika będzie miała dzięki temu łatwy dostęp do klasy odpowiednich urządzeń, bez potrzeby przeszukiwania listy innych losowych sprzętów, które przez przypadek korzystają z podobnego interfejsu”.
Dodał, że jeśli część jego kodu może być ponownie użyta do kolejnego podsystemu, który powstanie w przyszłości, to on nie ma nic przeciwko. Jednak na razie, łatka, którą przedstawił, adresuje aktualne potrzeby.
Powiedział ponadto, że niektórzy producenci korzystają z własnych, zamkniętych protokołów dla urządzeń GPS, których kodu łatwo nie poznamy, i w związku z tym nie możemy ich wspierać. Zauważył, że dla wielu z tych urządzeń najlepiej by było, gdyby pozostały w kwestii przestrzeni użytkownika. Nie ma potrzeby wkładać wsparcia dla nich do jądra, lepiej się skupić na tych, które łatwo rozpoznać.
Pavel powtórzył swoje zarzuty, że kod Johana nie jest prawdziwym podsystemem GNSS. Powiedział, że Johan powinien wybrać nazwę, która precyzyjniej oddaje to, co robi jego łatka. W ten sposób, kiedy wprowadzony zostanie prawdziwy podsystem GNSS, nie będzie problemu z już zajętą nazwą.
Jednak Johan odpowiedział: „Tu chodzi o grupowanie powiązanych urządzeń, które mają podobne funkcje. W tym przypadku jest to dostarczanie informacji o położeniu. Naprawdę nie rozumiem, jakim cudem uważasz, że typ klasy nazwany gnss może być w jakikolwiek sposób kontrowersyjny. […] Uważam, że nadanie podsystemowi służącemu odbiornikom GNSS nazwy gnss jest jak najbardziej sensowne”.
Zauważył, że jego łatka adresuje rzeczywiste potrzeby, i dodał, że jeśli Pavel znajdzie w przyszłości lepszy podsystem GNSS, może go wtedy dodać do jądra.
Johan przyjrzał się też specyfikacji Nokii N900, o której Pavel wspominał i powiedział:
„Usługa N900, do której wcześniej podałeś odnośnik, przetwarza dane telefonu, realizuje kilka obliczeń zmiennoprzecinkowych i tworzy zdania NMEA, przekazywane do pseudoterminala, którego część podrzędna jest otwierana przez gpsd.
Dane NMEA mogą równie dobrze być przekazywane do innego podsystemu jądra, na przykład gnss, zamiast tty. W tym miejscu mogą być dostępne dla standardowych interfejsów (na razie dla czystego interfejsu gnss, wraz z powiązanymi metadanymi). Dodatkowo, z tego co wiem, ugnss umożliwia też pozbycie się kilku sztuczek, związanych z odkrywaniem, kiedy GNSS jest otwierany i potrzebuje zasilania.
Wygląda więc na to, że interfejs ugnss będzie współpracował z N900, tak jak z każdym innym telefonem”.
Pavel nie zgodził się z pomysłem Johana na grupowanie urządzeń według ich funkcjonalności. Powiedział: „Zazwyczaj grupujemy urządzenia według interfejsu, a nie funkcjonalności”. Dodał, że jeśli teraz wybrana zostanie niepoprawna nazwa, później już się tego nie da naprawić.
Johan odpowiedział:
„Zacząłem od oddzielenia samego urządzenia gnss od czystego interfejsu (porównaj: HID), aby umożliwić coś takiego, ale im więcej się temu przyglądałem, coraz bardziej mi się wydawało, że planuję coś, co nigdy nie zostanie zrealizowane.
Przyjrzyj się niektórym dokumentom na stronie gpsd, dotyczącym protokołów GNSS i problemu odnajdywania znanych odpowiedników dla różnorakich, dostępnych urządzeń. Sam gpsd, w ciągu ostatnich dekad, miał już trzy wersje takich przyporządkowań. Nie jest to coś, co chcielibyśmy powtarzać w jądrze, które ma przecież zasady co do wstecznej kompatybilności i tym podobne reguły.
Dlatego, przynajmniej na razie, jestem przekonany, że czysty interfejs gnss jest najlepszy”.
W tym momencie Greg Kroah-Hartman jednym gestem uciął całą dyskusję. Zaakceptował łatkę, mówiąc: „Wygląda świetnie. Dzięki za całą pracę i dodanie nowego podsystemu dla czegoś, o co ludzie prosili od wielu lat. Łatkę dołączyłem już do mojego drzewa. Dobra robota!”
Pavel odpowiedział, że dyskusja jeszcze się nie skończyła. Powtórzył swoje podstawowe zarzuty, mówiąc: „Nie ma tu nic związanego z GNSS. W kodzie nie ma informacji o formacie danych, które są przekazywane (możemy jedynie zgadywać, że charakterystyka przepływu danych jest spotykana w GNSS). Poza tym zabiera się nazwę potrzebną dla prawdziwego podsystemu GNSS. Proszę, nie róbcie tego”.
Jednak Johan odpowiedział: „To jest prawdziwy podsystem GNSS. Pogódź się z tym”. Greg dodał, że z jego punktu widzenia dyskusja się skończyła. Powiedział: „To tylko pojedynczy zestaw łatek i nikt inny nie dostarczył alternatywy. Jeśli się okaże, że jest to niezbyt dobre API, wtedy rozwiążemy problem, ale teraz możemy to wypróbować”.
I tak się to skończyło.
Rzadki to widok, kiedy jedna z ważniejszych osobistości w społeczności jądra (Greg) ucina tak gwałtownie dyskusję drugiej ważnej osobistości (Pavel). Pamiętajmy jednak, że kod Johana rozwiązuje rzeczywiste problemy, a żadne alternatywy się nie pojawiły. Wydaje się, że jedną z zasad rozwoju Linuksa jest akceptowanie rozwiązań, które nie są idealne. Częściowo jest tak dlatego, że są to w końcu rozwiązania, a częściowo, ponieważ zmusza krytyków do tworzenia swoich wersji lub milczenia. Linus Torvalds, lata temu, zastosował ten sposób w przypadku BitKeepera. Chociaż krytykujący nie dostarczyli wtedy lepszej alternatywy, to była to dobra, tymczasowa łatka i ostatecznie dzięki niej powstał system kontroli wersji Git, dzięki czemu świat stał się lepszy.
Jian-Hong Pan chciał się dowiedzieć, czy twórcy jądra wspierają nowy podsystem LoRaWAN. Wyjaśnił: „LPWAN (Low-Power Wide-Area Network) to typ rozległej, bezprzewodowej sieci telekomunikacyjnej, pozwalającej na komunikację na dużych odległościach pomiędzy podłączonymi urządzeniami, takimi jak na przykład czujniki zasilane bateriami. Może być wykorzystywana razem z Internetem Rzeczy (IoT). LoRaWAN, czyli jeden ze sposobów implementacji LPWAN, to protokół warstwy sterowania z dostępem do medium transmisyjnego (MAC – medium acces control), wykorzystywany na potrzeby komunikacji pomiędzy bramkami LPWAN i podłączonymi urządzeniami”.
Zapytał: „Jeśli LoRaWAN stanie się podsystemem Linuksa, to czy możemy, lub też czy powinniśmy dodać teraz definicje do odpowiednika plików nagłówkowych jądra?” Opublikował odnośnik do swojego repozytorium Git, w którym znajduje się to, co do tej pory utworzył: https://github.com/starnight/LoRa/tree/lorawan-ndo/LoRaWAN.
Jirí Pírko zauważył, że to repozytorium nie wystarczy – Jian-Hong powinien przesłać łatkę do drzewa jądra.
Marcel Holtmann dodał: „Kiedy publikujesz swój podsystem LoRaWAN do NetDev do oceny, dołącz łatkę, która dodaje definicje nowych rodzin adresów. Po prostu wybierz dostępne numery. I tak nie zdecydujemy się na żadne konkretne liczby dopóty, dopóki Twoja praca nie zostanie zaakceptowana. Oznacza to, że numer może się zmienić, jeśli inne rodziny adresów zostaną włączone przed Twoją . Będziesz więc musiał dorzucać aktualizacje. Ostatecznie glibc przyjmie numer przydzielony przez jądro”.
Odpowiedzi udzielił też Andreas Färber, który powiedział, że od roku pracuje nad podobnym projektem. Podał odnośnik do swojego kodu: https://github.com/afaerber/lora-modules.
Andreas spytał Jian-Honga, czy uważa, że ich projekty są niezależne, czy może wręcz przeciwnie.
Jain-Hong odpowiedział: „Wow! Super! Mam nowych przyjaciół:)”.
Oznajmił, że wygląda na to, że ich projekty opierają się na tym samym pomyśle i postanowił przejść do szczegółowej analizy możliwych obszarów zazębiania się obu rozwiązań. Jednak dyskusja skończyła się w tym miejscu, prawdopodobnie dlatego że Andreas i Jian-Hong wymienili się e-mailami.
Zdarza się, że dwóch deweloperów nagle odkrywa, że pracują nad tym samym problemem. Wydaje się, że podstawową częścią filozofii reagowania na problemy jest to, że w danym czasie więcej niż jedna osoba może zwrócić uwagę na konkretny z nich. Czasami programista przez długi czas może rozwiązywać daną kwestię prywatnie, nie chcąc przedstawiać swojego projektu dopóty, dopóki nie będzie w stanie go obronić. Czasami dwa projekty podchodzą do problemu z tak różnych punktów widzenia, że wykluczają się nawzajem: mają na przykład dwa różne harmonogramy, odmienne sposoby zamykania procesu lub zarządzania obciążeniem. Jednak dwie różne implementacje tego samego, znanego protokołu, mają dużo większe szanse na połączenie i ulepszenie siebie nawzajem niż na stworzenie nowego konfliktu interesów.
Przypuszczam, że Andreas i Jian-Hong połączą projekty, utworzą zespół i włączą swój kod do jądra dwa razy szybciej, niż gdyby pracowali oddzielnie.
Masahiro Yamada opublikował ostatnio dokumentację dla nowych elementów Kconfig, o którą w lutym prosił Linus Torvalds. Chodziło o to, że do procesu budowy pakietu w jądrze dołączono wiele problematycznych testów dla różnych funkcji kompilatora, obsługujących opcje jądra, które zależą od tego, jaki kompilator jest zainstalowany. Aktualnie nie ma możliwości poznać takich szczegółowych danych w czasie fazy konfiguracji.
Linus chciał, aby Kconfig posiadał funkcje, którym na danej wersji kompilatora dadzą możliwość określenia zależności, dzięki czemu będą one znane w czasie konfiguracji, a nie kompilacji. W ten sposób wyczyści się pliki makefile i całość będzie łatwiejsza do opanowania. Dodatkowo, przyszli programiści jądra będą mieli ułatwione zadanie, gdyż dodając nowe funkcje, nie będą zmuszani do gruntownego poznawania wersji kompilatora.
Masahiro udokumentował odpowiednie dodatki do języka. Zawierają one zestaw definicji dla zmiennych i zależności, podobny do tego, co zawiera make. Prawdę mówiąc, make był wykorzystany jako model dla ulepszeń w Kconfig.
Kees Cook pochwalił dokumenty, chociaż wolałby, aby były napisane w języku znaczników, zamiast zwykłym tekstem. Zaakceptował łatkę. Randy Dunlap również miał kilka małych uwag i zaakceptował łatkę.
Dyskusji w zasadzie nie było. Funkcje, które podobają się Linusowi, są zwykle implementowane szybko i wpisywane do drzewa bez większych problemów.
Changbin Du z Intela opublikował łatkę tylko dla programistów jądra, dzięki której będą oni mieli możliwość zablokowania standardowej obsługi funkcji otwartych (inline). W języku C oznaczenie w ten sposób funkcji mówi kompilatorowi, aby nie wykonywał do niej skoku podczas wywołania, ale skopiował jej kod bezpośrednio w miejsce wywołania. Wadą takiego rozwiązania jest to, że skompilowany plik binarny pełen jest kopii tej samej funkcji, jednak zaletą jest szybkość działania kodu, gdyż brak jest kosztownych skoków przy każdym wywołaniu funkcji.
Jednak GCC może również sam ocenić, kiedy ze zwykłej funkcji zrobić funkcję otwartą. Jest to wspaniała opcja, dzięki której GCC zwraca szybciej działające programy. Jednak efekt uboczny jest taki, że niektóre narzędzia do debugowania stają się mniej efektywne, na przykład program śledzący funkcje jądra sprawdza jedynie te, które nie są otwarte.
Łatka Changbina powstrzymywała GCC przed zamienianiem zwykłych funkcji w otwarte. Oznacza to, że o wiele więcej funkcji może być analizowanych przez program śledzący funkcje jądra.
Wyniki były niezwykłe. Program śledzący funkcje natychmiast zaczął znajdować błędy w całym jądrze, w obszarach, których wcześniej nie mógł testować.
Steven Rostedt był pod dużym wrażeniem możliwości wykrywania w całym jądrze błędów po zastosowaniu łatki. Zaskoczony też był Johan Hovold, ale zauważył jedno z ostrzeżeń, które łatka zwróciła, a które było nieprawdziwe. Zapytał, czy jest możliwość oszukania testowego kodu, tak aby ten jeden przypadek został pominięty. Steven zasugerował małą zmianę kodu jądra, dzięki czemu ostrzeżenie zniknie.
Viresh Kumar przyjrzał się temu fałszywemu ostrzeżeniu i stwierdził: „Nie jestem pewien, jakie rozwiązanie byłoby najlepsze do wyeliminowania tego fałszywego ostrzeżenia”. W tym przypadku chodzi o to, że kod w jednym konkretnym miejscu alokuje pamięć, ale nie czyści bufora RAM, zanim z tego skorzysta. Nie wiadomo też, dlaczego fałszywe ostrzeżenie pojawiło się tylko w dwóch z czterech przypadków w danym pliku.
Johan zasugerował, że pomysł naprawy tego przypadku nie jest najlepszy i „prawdopodobnie najlepiej jest zostawić wszystko tak jak jest, a ludzie od GCC znajdą sposób na obsługę takich fałszywych ostrzeżeń”. Stwierdził, że wszystkie próby naprawy źródeł jądra mogłyby być zbyt skomplikowane. Viresh zgodził się, że mogą pozostawić sytuację taką, jaka jest, gdyż nic złego się nie dzieje.
W międzyczasie Steven opracował łatkę, która pozbywa się fałszywych ostrzeżeń, ale Johan stwierdził, że jest ona zbyt skomplikowana i dodał: „Czy powinniśmy obchodzić w ten sposób błędy w GCC? Jeśli implementacja tego nowego ostrzeżenia nie jest zbyt dobrym rozwiązaniem, to czy nie powinno się go zamiast tego wyłączyć?”
W tym momencie dyskusja się zakończyła. Jak dla mnie interesujące było to, jak wiele uwagi poświęca się niewielkim sprawom, tylko dlatego, że nie do końca są dopasowane. Kod Changbina działał i wykrywał błędy w całym jądrze. Najprawdopodobniej zostaną one naprawione. Jednak kilka fałszywych ostrzeżeń (a nie błędów jądra) wywołało dyskusję na temat najlepszych praktyk alokowania pamięci, możliwości oszukania GCC, tak aby dawał pożądany wynik i wreszcie decyzję o pozwoleniu GCC na zwracanie fałszywych ostrzeżeń, dzięki czemu ludzie odpowiedzialni za GCC będą mogli znaleźć błąd i go naprawić.
Autor
Zack Brown
Lista dyskusyjna poświęcona rozwojowi jądra jest głównym narzędziem komunikacyjnym programistów jądra. Ruch na nie jest ogromny – dochodzi do dziesięciu tysięcy listów tygodniowo. Pozostawanie ze wszystkim na bieżąco to zadanie bardzo trudne dla zwykłych śmiertelników. Zack Brown jest jedną z niewielu osób, która uważnie śledzą wszystkie dyskusje.