Wywołania systemowe Uniksa
Linux jest darmowy, o ile twój czas jest bezwartościowy.
- Jamie Zawinski
Wywołania systemowe Uniksa – zbiorowisko luźno powiązanych ze sobą funkcji ukrytych gdzieś w trzewiach biblioteki libc. Wywołana funkcja może się wykonać i (jeśli ma na to ochotę) zwrócić nic nie mówiące errno. Standardowe wywołania opisuje dokumentacja POSIX, którą można streścić następująco:
Zachowanie jest niezdefiniowane. |
Początkującym programistom zalecamy wyrycie sobie tej złotej sentencji na ścianie nad monitorem i spoglądanie na nią w razie jakichkolwiek wątpliwości.
Zanim przejdziemy do części właściwej artykułu, warto zastanowić się kogo właściwie obchodzi coś nazwane tak cudacznie jak wywołania systemowe Uniksa? W normalnych warunkach powinno to być kilku piwniczaków, którzy piszą niskopoziomowe programy na Linuxie. Jednak z jakiegoś niejasnego powodu wykładowcy kierunków informatycznych katują studentów bezużytecznymi syscallami, rozszerzając grupę wtajemniczonych piwniczaków kilkukrotnie.
Zarządzanie procesami[edytuj • edytuj kod]
W celu skuteczniejszego siania chaosu i pszenicy wśród procesora, RAMu i peryferiów, system jednocześnie uruchamia wiele procesów, które nieustannie konkurują o dostęp do zasobów. Rezultatem jest nieokiełznany bajzel, do kontrolowania którego zostaje zmuszony Bogu ducha winny programista, a za jego błędy cierpi użytkownik. Sam sprawca całego pierdolnika – Szatan system operacyjny jest święty i ma zawsze rację.
fork
– zaczynamy z grubej rury, czyli od funkcji, która potrafi stworzyć coś z niczego, zwrócić dwie różne wartości i na dodatek debilnie się nazywać. Jak sama nazwa wskazuje,fork
dziabie kernel widelcem gdzieś pomiędzy planistą, a zarządzaniem pamięcią. Wkurzony nie na żarty kernel dla świętego spokoju robi procesowi dziecko i na odchodne wsadza mu widelec w wiadome miejsce.
exec
– funkcja zazwyczaj wykonywana pofork
żeby nieco złagodzić ból po bo bolesnej interakcji z jądrem. Pozwala procesowi przeszczepić sobie wszystkie organy innego programu, zostawiając jedynie PID i parę niezdefiniowanych interakcji. Jak łatwo się domyślić, funkcjaexec
wcale nie istnieje, a programista powinien skorzystać zexecl
,execle
,execlp
,execv
,execve
lubexecvp
. Zrozumienie co robią poszczególne wersje zostawiam jako ćwiczenie dla studentów.
exit
– kiedy proces ma już dość życia na ziemskim padole łez, decyduje się na krok ostateczny i wykonuje funkcjęexit
. Za argument można podać 0 (czyli jest dobrze), albo jeden z pierdyliarda kodów błędu, które są kompletnie niezdefiniowane i nie mają żadnego znaczenia. W momencie popełnienia seppuku proces wysyła jeszcze rodzicowi liścik pożegnalny w postaciSIGCHLD
. Jest to jeden z nielicznych sygnałów, który nie zabije trafionego procesu, ale za to musi zostać obsłużony bo tak.
wait
– jak sama nazwa wskazuje,wait
służy do czekania na dzieci aż się zabiją, za wyjątkiem sytuacji, gdy na nie nie czekamy. Przy okazji możemy otrzymać kod, jaki dziecko przekazało doexit
, co oczywiście nic nam nie mówi, bo może znaczyć cokolwiek. Jeśli nie zaczekamy na martwe dziecko to zamieni się ono w zombie. Dodatkowo, jeśli rodzic umrze niewywaitowawszy dzieci, to zombie staną się sierotami i… No generalnie syf się robi, lepiej waitować.
Sygnały[edytuj • edytuj kod]
kill
– jak mawia stare polskie przysłowie: nie machaj tym drągiem baranie na oślep bo jeszcze komuś przypisz. Zasada ta nie dotyczy sygnałów w Uniksie, bo strzelanie sygnałami przypomina nieco operowanie drewnianą armatą po pijaku. Tutaj nie da się nie machać na oślep, bo nigdy nie wiadomo w co trafisz i jak zareaguje na to dany proces. Równie dobrze armata może ci wybuchnąć w twarz i przedwcześnie zakończyć zabawę.
sigaction
– coby nieco okiełznać pierdolnik wywoływany przez różnorakie sygnały, można kazać procesowi reagować w określony sposób na niektóre z nich. Sposób bardzo biedny, bo przerywający działanie głównego wątku interruptem i przerzucający kontrolę w pizdu do handlera.
sigsuspend
– funkcja zawieszająca program aż do otrzymania jednego z sygnałów z podanej maski. Wtedy wykonuje domyślną dyspozycję (zazwyczaj wywalenie procesu) albo odpala handler ustawiony przy pomocysigaction
. Podobno jest lepsze od zwykłegosleep
.
sigwait
– ucywilizowana wersja powyższego. Zamiast cudować z handlerami po prostu zwraca numerek otrzymanego sygnału. Brawo. Nie można tak było od razu?
Obsługa plików[edytuj • edytuj kod]
open
– otwiera plik/socket/urządzenie blokowe/pralkę/piwo/cokolwiek co może być traktowane jako plik w Uniksie. Żeby było śmieszniej, nie zwraca wskaźnika na jakąś strukturę (jak np. wysokopoziomowyfopen
), tylko numerek deskryptora, który nic nie mówi. Całością zajmuje się jądro i programista jest zdany na jego łaskę lub niełaskę. Można też podać jakieś śmieszne flagi, w styluO_RDONLY
, czyO_APPEND
, ale efekt końcowy i tak jest losowy.
close
– tu nawet nie musimy się wysilać, wystarczy że zacytujemy ciocię Wikipedię: W dawnych czasachclose
nie zwracało kodu błędu, więc nikt go nie sprawdzał. Współcześnie zwraca kod błędu, co z punktu widzenia architektury systemu jest kompletnym nieporozumieniem – nikt tak naprawdę nie zdefiniował co konkretnie ma znaczyć błąd przy zamykaniu pliku i co program ma z tym zrobić.
- Powyższy tekst można śmiało uzupełnić o informację, że cały POSIX to jedno wielkie nieporozumienie.
read/write
– jak już se plik otworzymy to wreszcie możemy z niego czytać (lub zapisywać doń) surowe bajty. Pokazujemy funkcji jakiś bufor i modlimy się, żeby się nie przepełnił. Obie te funkcje zwracają całą gamę błędów, od złej flagi, przez przeciekające rury, po interwencję siły wyższej.