Wywołania systemowe Uniksa: Różnice pomiędzy wersjami
Ostrzyciel (dyskusja • edycje) M (co tu się) |
M (Wycofano ostatnie edycje autorstwa 89.64.44.179; przywrócono ostatnią wersję autorstwa Ja8czy coś.) Znacznik: rewert |
||
(Nie pokazano 13 wersji utworzonych przez 5 użytkowników) | |||
Linia 1: | Linia 1: | ||
{{Cytat|Linux jest darmowy, o ile twój czas jest bezwartościowy.|Jamie Zawinski}} |
|||
⚫ | Zanim przejdziemy do części właściwej [[artykuł]]u, warto |
||
[[Plik:Linux kernel System Call Interface and glibc.svg|thumb|250px|Kompatybilne jednocześnie z POSIX i Linux? W jakim świecie ty żyjesz, że w to wierzysz?]] |
|||
⚫ | '''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: |
||
Nie zniechęciło cię to jeszcze? |
|||
⚫ | |||
⚫ | '''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: |
||
⚫ | |||
Początkującym programistom zalecamy wyrycie sobie tej złotej sentencji na ścianie nad [[monitor]]em i spoglądanie na nią w razie jakichkolwiek wątpliwości. |
Początkującym programistom zalecamy wyrycie sobie tej złotej sentencji na ścianie nad [[monitor]]em 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 [[Informatyk|piwniczaków]], którzy piszą niskopoziomowe programy na [[Linux]]ie. 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 == |
== Zarządzanie procesami == |
||
W celu skuteczniejszego siania chaosu i pszenicy wśród procesora, [[RAM]]u 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 [[Bóg|Bogu]] ducha winny programista, a za jego błędy cierpi użytkownik. Sam sprawca całego pierdolnika – <del>[[Szatan]]</del> system operacyjny jest święty i ma zawsze rację. |
|||
=== <code>fork</code>, czyli robienie dzieci widelcem === |
|||
* '''<code>fork</code>''' – 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, <code>fork</code> dziabie kernel [[Widelec|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 [[Dupa|wiadome miejsce]]. |
|||
⚫ | * '''<code>exec</code>''' – funkcja zazwyczaj wykonywana po <code>fork</code> ż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ć, funkcja <code>exec</code> wcale nie istnieje, a programista powinien skorzystać z <code>execl</code>, <code>execle</code>, <code>execlp</code>, <code>execv</code>, <code>execve</code> lub <code>execvp</code>. Zrozumienie co robią poszczególne wersje zostawiam jako ćwiczenie dla studentów. |
||
* '''<code>exit</code>''' – kiedy proces ma już dość życia na ziemskim padole łez, decyduje się na krok ostateczny i wykonuje funkcję <code>exit</code>. 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 postaci <code>SIGCHLD</code>. Jest to jeden z nielicznych sygnałów, który nie zabije trafionego procesu, ale za to musi zostać obsłużony ''[[bo tak]]''. |
|||
* '''<code>wait</code>''' – jak sama nazwa wskazuje, <code>wait</code> 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 do <code>exit</code>, 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 == |
|||
[[Plik:Operation Upshot-Knothole - Badger 001.jpg|thumb|250px|<code>kill(-1, SIGKILL);</code>]] |
|||
* '''<code>kill</code>''' – jak mawia stare polskie przysłowie: ''nie machaj tym drągiem baranie na oślep bo jeszcze komuś przyp{{cenzura3}}isz''. Zasada ta nie dotyczy sygnałów w [[Unix|Uniksie]], bo strzelanie sygnałami przypomina nieco operowanie [[Drewniana armata|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ę. |
|||
* '''<code>sigaction</code>''' – 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. |
|||
* '''<code>sigsuspend</code>''' – 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 pomocy <code>sigaction</code>. Podobno jest lepsze od zwykłego <code>sleep</code>. |
|||
* '''<code>sigwait</code>''' – 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 == |
|||
* '''<code>open</code>''' – otwiera plik/socket/[[Dysk twardy|urządzenie blokowe]]/[[Pralka|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. wysokopoziomowy <code>fopen</code>), 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 stylu <code>O_RDONLY</code>, czy <code>O_APPEND</code>, ale efekt końcowy i tak jest losowy. |
|||
* '''<code>close</code>''' – tu nawet nie musimy się wysilać, wystarczy że zacytujemy ciocię Wikipedię: '' W dawnych czasach <code>close</code> 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. |
|||
* '''<code>read/write</code>''' – 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ę [[Bóg|siły wyższej]]. |
|||
== Zobacz też == |
|||
* [[Unix]] |
|||
* [[powłoka (Linux)]] |
|||
* [[Linux]] |
|||
* [[X Window System]] |
|||
{{Linux}} |
|||
{{stopka}} |
|||
=== <code>exec</code>, czyli jak nie przeładowywać funkcji === |
|||
[[Kategoria:Unix]] |
|||
⚫ | |||
[[Kategoria:Programowanie]] |
Aktualna wersja na dzień 18:01, 19 paź 2023
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.