W programowaniu wielowątkowym zdarza się bardzo wiele problemów, wynikających z tego, że program wykonuje się współbieżnie w wielu wątkach naraz i niestety istnieje potrzeba dostępu do współdzielonych zasobów oraz sygnalizacji pewnych zdarzeń. Deadlockami straszą rozmaite podręczniki o programowaniu a za nimi wykładowcy zajęć z programowania wielowątkowego czy systemów operacyjnych. Zupełnie niepotrzebnie, bo w programowaniu wielowątkowym dużo poważniejsze problemy powodują rozmaite wyścigi, jeśli programista zapomniał o umieszczeniu gdzieś sekcji krytycznej, albo tzw. lockouty, wynikające często z braku (lub błędu) sygnalizacji, a na deser pozostają problemy powstałe przez nieodpowiedzialne pląsanie po stercie procesu, współdzielonej przecież przez wszystkie wątki, czyli heap corruption. Deadlock w katalogu wszystkich bugów wydaje się najmniejszym zmartwieniem. Tutaj z reguły wystarczającym rozwiązaniem jest uruchomienie debuggera i skorzystanie z oczu.
Archiwum kategorii: linux
Śledzenie zużycia pamięci
Obecnie programiści dużo rzadziej zwracają uwagę na to, ile pamięci zużywa aplikacja, nad którą pracują. Komputery osobiste mają gigantyczne zasoby RAMu, spokojnie wystarczające do obsługi zasobochłonnych aplikacji, głównie gier. Pamięć wirtualna pozwala z kolei uwolnić się od zmartwień o pamięć fizyczną, ot najwyżej dysk będzie trochę chrobotał od czasu do czasu. Programiści z kolei mają dodatkowo do dyspozycji języki programowania, w których praktycznie wcale nie muszą się martwić o zarządzanie pamięcią. Problem poprawnej alokacji i dealokacji załatwiają przeróżne garbage collectory.
Są jednak takie obszary, w których programiści muszą się liczyć z ograniczonymi zasobami. Jednym z takich obszarów jest oprogramowanie serwerowe, szczególnie takie, które w założeniu musi być wysokowydajne, na przykład takie, które relizuje strumieniowanie multimediów. Aplikacja musi utrzymywać po swojej stronie znaczne bufory na ramki wideo dla poszczególnych plików/kanałów. Zbyt wielu użytkowników naraz i nagle pamięć fizyczna ulega wyczerpaniu, co doprowadza do swap’owania aktualnie nieużywanych stron pamięci na dysk. To z kolei powoduje olbrzymi spadek wydajności aplikacji i może doprowadzić do problemów z funkcjonowaniem usług.
Drugim obszarem są systemy wbudowane (embedded). Z reguły zasoby takich komputerów są mocno ograniczone i o rzędy wielkości mniejsze, niż zasoby komputerów osobistych. Mimo, że w wielu architekturach jednostka zarządzania pamięcią (MMU – Memory Management Unit) jest dostępna i wykorzystywana przez system, to może się okazać, że nie ma co liczyć na swap. Ale nierzadko MMU zwyczajnie nie ma, a pamięć fizyczna jest adresowana wprost. Wtedy zarządzanie pamięcią staje się jednym z kluczowych zadań – programista nagle zaczyna zwracać uwagę na takie subtelności, jak wielkość pliku wykonywalnego, wielkości bibliotek, rozmiary stosów, alokacje statyczne podczas inicjalizacji.
Niezależnie od charakteru tworzonej aplikacji, zawsze warto wiedzieć, jak sprawdzić zużycie pamięci przez proces, stąd kilka rad.
Demonizacja procesu – linux
Ech… blog miał być o cyfrowym audio/wideo, a tu linux i demony.
Ukończyłem wstępną implementację pewnej aplikacji, która docelowo ma działać jako demon w systemie, czyli działać bezustannie jako usługa, bez bezpośredniej interakcji z poziomu terminala. Typowe aplikacje „konsolowe”, czy to interaktywne, czy nie, po uruchomieniu przypisane są po pierwsze do procesu macierzystego, czyli shella (np bash), a po drugie do terminala sterującego (controlling terminal), którym może być terminal lokalny (tty, konsole w trybie tekstowym komputera), terminal realizowany przez port szeregowy lub modem, czy też pseudoterminal kontrolowany czy to przez serwer zdalnego shella (telnet, ssh), czy przez okienkową aplikację terminala (np. gnome-terminal). Taka aplikacja jest aplikacją interaktywną, zamknięcie czy to shella, czy też terminala poprzez np. przerwanie połączenia powoduje, że shell wysyła do swoich potomków sygnał hang up (czyli SIGHUP) historycznie symbolizujący odłożenie słuchawki telefonu-modemu. Demon, to proces działający bez „pana”, jedynym zwierzchnikiem jest proces init, a demon nie korzysta z terminala, czyli nie posiada standardowego wyjścia, wejścia czy strumienia błędów (stdout, stdin, stderr). Jak przygotować aplikację do roli demona?