Procesy w Linuksie

1. Podstawy
Na początek warto poznać definicję procesu, oraz kilka innych terminów z nim związanych. Mówiąc najogólniej proces jest wykonywanym programem, który posiada pewien stan:
    nowy – proces właśnie został utworzony
    gotowy – proces znajduje się w pamięci czeka na wykonanie swojego kodu przez procesor
    działający – proces, który aktualnie jest wykonywany przez procesor
    zablokowany – proces oczekujący na przydzielenie danego zasobu
    zakończony – proces kończący działanie
Proces otrzymuje dostęp do zasobów takich jak np.: procesor, pamięć, pliki, urządzenia wejścia – wyjścia. Każdy posiada swój unikalny identyfikator liczbowy PID (ang. Process ID) oraz identyfikator rodzica (PPID – ang. Parent Process ID) czyli procesu który go utworzył. Tak więc uruchomione procesy można przedstawić w formie drzewa, w którego korzeniu znajdować się będzie proces z PID równym jeden – init, uruchamiany jako pierwszy po załadowaniu jądra. Podobnie jak pliki procesy posiadają swoich właścicieli, zazwyczaj są to użytkownicy którzy uruchomili dany program, wyjątkiem jest tu program z ustawionym bitem setuid lub też setgid. Prawa dostępu do zasobów systemu (np. plików w katalogu /dev), użytkownika który uruchomił proces, określają prawa dostępu jakie będzie posiadał proces. Do komunikacji z procesami wykorzystywane są tzw. sygnały. Programy uruchomione są z różnym priorytetem, określanym liczbą nice, przyjmującą wartości od -20 (najwyższy) do 19 (najniższy), domyślna wartość to 0.


2. fg, bg, jobs
Terminal umożliwia uruchamianie kilku programów naraz, przełączanie się pomiędzy nimi polega na przesuwaniu programu z „pierwszego planu” w „tło”. Tylko pierwszoplanowy proces może odbierać dane od użytkownika. Przesuwanie procesów z tła na pierwszy plan i w drugą stronę porównać można do aktywnego okna które przykrywa, pozostałe, nieaktywne okna.

Aby uruchomić program w tle wystarczy na końcu polecenia dostawić znak & (ang. Ampersand).
$ mpg123 -q plik.mp3&
[1] 638
$
Uruchamiając mpg123 w tle mogę słuchać muzyki mając cały czas dostęp do powłoki. Powłoka w nawiasie kwadratowym podała mi numer zadania (ang. job) - 1, oraz numer PID - 638.
Aby wyświetlić listę uruchomionych w tle zadań, należy użyć polecenia jobs, posiada ono dodatkowy parametr -l podający dodatkowo numer PID danego zadania.
Aby zatrzymać proces pierwszoplanowy należy użyć kombinacji Ctrl + z (w tym przypadku do procesu zostanie wysłany sygnał SIGSTP), aby zatrzymać proces można posłużyć się kombinacją Ctrl + c, przesłany zostanie do procesu sygnał SIGINT .

$ jobs -l
[1]-   638 Running                 mpg123 -q plik.mp3 &
[2]+   878 Stopped (tty output)    mc
W tle uruchomione zostały dwa zadania, mpg123 jest uruchomiony ponieważ do działania nie potrzebuje interakcji z użytkownikiem, mc jest zatrzymany i czeka na dane od użytkownika.
Aby dany proces uczynić pierwszoplanowym, należy posłużyć się poleceniem fg %numer zadania, lub fg %?nazwa plecenia lub fragment nazwy.
$ fg %1
$ fg %mpg
W pierwszym przypadku przeniosłem zadanie na pierwszy plan odwołując się do jego numeru zadania, w drugim odwołując się po fragmencie nazwy.
Polecenie bg %numer zadania, uruchomi zatrzymane w tle zadanie, w przeciwieństwie do polecenia fg, nie przeniesie zadania na pierwszy plan.
$ mpg123 -q plik.mp3
Ctrl + z
[3]+  Stopped                 mpg123 -q plik.mp3
$ bg %3
[3]+ mpg123 -q plik.mp3 &
Na koniec warto zwrócić uwagę na jeden fakt, na ekranie pojawią się dane wysyłane przez program w tle na standardowe wyjście, wyjście błędów, aby tego uniknąć można przekierować strumień do śmietnika np.polecenie > /dev/null


3. ps, pstree
Przedstawione wcześniej polecenie jobs, wyświetlało procesy uruchomione na danym terminalu. Aby wyświetlić szczegółowy spis procesów uruchomionych w systemie można posłużyć się poleceniem ps, uruchomione bez parametrów zadziała tak jak jobs. Pełny spis wszystkich parametrów dostępny jest w podręczniku tego polecenia (man ps), poniżej kilka najciekawszych opcji:
    -e wyświetli każdy proces uruchomiony w systemie
    -l szczegółowy opis
    -f opis szczegółowy, krótszy od -l
    -H pokazuje spis procesów w formie drzewa
    a wyświetla wszystkie procesy
    x wyświetla procesy uruchomione bez terminala
    u podaje nazwę użytkownika który uruchomił proces
    f wyświetla procesy w formie drzewa
Ps przyjmuje parametry w dwóch, nie kompatybilnych ze sobą, formatach: System V (parametry z myślnikiem -), oraz BSD. Wyjście polecenia z parametrami aux będzie wyglądać:
$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1   2952  1852 ?        Ss   10:49   0:01 /sbin/init
adam      5623  0.0  0.6  27892  7100 ?        Ssl  10:51   0:00 /usr/bin/gnome-session
adam      6815  0.2  1.6  39880 16728 ?        S    11:11   0:14 gedit
adam      7105  0.0  0.2   5708  3060 pts/1    Ss   11:16   0:00 bash
Poszczególne kolumny oznaczają:
    USER – nazwa użytkownika, właściciela procesu
    PID – identyfikator procesu
    %CPU – szacowany procent użycia procesora, obliczany poprzez podzielenie czasu użycia procesora przez proces, przez czas uruchomienia
    %MEM – szacowany procent użycia pamięci
    VSZ – ilość użytej pamięci wirtualnej w KB
    RSS – wykorzystana pamięć fizyczna w KB
    TTY – terminal na którym uruchomiono proces
    STAT – stan procesu, D oczekujący na dane z I\O, R działający, S uśpiony, T zatrzymany, X proces martwy(nie powinien być wyświetlany), Z proces zombie
    START – godzina uruchomienia procesu
    TIME – łączny czas zużycia procesora
    COMMAND – polecenie które uruchomiło proces
Polecenie pstree, wyświetla procesy w formie drzewa, posiada parametr -a wyświetlający polecenie które uruchomiło proces.
$ pstree -a
init
  ├─cupsd
  ├─dbus-daemon --system
  ├─gedit
  └─gnome-terminal
      ├─bash
      │   └─man ps
      │       └─pager -s
      ├─bash
      │   └─man ps
      │       └─pager -s
      └─bash
          └─pstree -a

3. top
Polecenie top umożliwia podgląd uruchomionych procesów w systemie w czasie rzeczywistym. Parametr -u nazwa użytkownika umożliwia podgląd procesów uruchomionych tylko wybranego użytkownika, -pPID pozwala na podgląd procesu o określonym PID, przy czym parametr ten może zostać podany do 20 razy.
$ top
top - 17:38:09 up 43 min,  2 users,  load average: 0.32, 0.17, 0.06
Tasks: 124 total,   1 running, 123 sleeping,   0 stopped,   0 zombie
Cpu(s):  1.5%us,  0.2%sy,  0.0%ni, 98.3%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1026304k total,   560996k used,   465308k free,    42120k buffers
Swap:  1020116k total,        0k used,  1020116k free,   246652k cached
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 7391 adam      15   0  189m  56m  21m S    3  5.6   0:20.42 firefox-bin
 7517 adam      15   0  2368 1164  876 R    1  0.1   0:00.03 top
 4029 root      13  -2  1744  384  280 S    0  0.0   0:00.76 ipw3945d-2
Aby zamknąć program należy posłużyć się przyciskiem q, niektóre przydatne skróty:
    F lub O zmienia kolejność sortowania
    spacja odświeża ekran
    < ,> zmienia kolejność sortowania, wg. wyświetlanych kolumn
    r zmienia wartość nice procesu
    W zapisuje bieżące ustawienia top do pliku ~/.toprc
    k wysyła sygnał do procesu

4. htop
Htop wyświetla listę procesów w bardziej rozbudowanej graficznie formie, program ten korzysta z biblioteki ncurses, zazwyczaj nie jest domyślnie dostępny.
    kursory – poruszanie się pomiędzy procesami
    F1 – menu pomocy
    F2 – ustawienia
    F3 – wyszukaj proces
    F4 – odwraca sortowanie
    F5 – wyświetla procesy w formie drzewa
    F6 – zmienia kolejność sortowania
    F7 – zmniejsza priorytet wybranego procesu
    F8 – zwiększa priorytet wybranego procesu
    F9 – wysyła sygnał do procesu
    F10 – kończy program

5. kill
Wysyła sygnały procesom, składnia to kill sygnał PID, domyślny sygnał to SIGTERM (wartość liczbowa: 15), „delikatnie” kończący działanie programu pozwalający zamknąć otwarte pliki i „posprzątać” po swoim działaniu. Mocniejszym w działaniu procesem jest SIGKILL (wartość 9) wymuszający natychmiastowe zakończenie programu, sygnały SIGSTOP oraz SIGCONT odpowiednio zatrzymują i wznawiają wykonanie procesu. Procesowi można wysłać sygnał używając jego nazwy, lub korzystając z wartości liczbowej.
kill -SIGKILL 7496
kill -9 7496
W obu przypadkach zostanie „zabity” proces od PID 7496.


6. killall
W tym poleceniu moża przesłać sygnał wykorzystując nazwę procesu (można użyć wyrażeń regularnych) np.:
killall mplayer
Zabije wszystkie procesy o nazwie mplayer. Ciekawym parametrem jest -l, wyświetlający wszystkie możliwe sygnały. W niektórych systemach np. Solaris polecenie to zabija wszystkie procesy jakie użytkownik jest w stanie zabić, uruchomione przez roota zakończy działanie systemu.


7. nohup
Polecenie to związane jest z sygnałem SIGHUP. Historycznie sygnał ten informował o utracie połączenia z terminalem. Obecnie wykorzystywany jest do informowania, że pseudo-terminal na którym uruchomiono program zakończył działanie, przez co programy uruchomione na tym terminalu też są kończone. Proces uruchomiony z poleceniem nohup będzie ignorował ten sygnał.
$ nohup pidgin
nohup: dołączanie wyników do `nohup.out'
Jeżeli wcześniej wyjście programu nie zostało przekierowane do pliku, nohup domyślnie przekieruje je do nohup.out.


8. pidof, pgrep
To dwa małe ale przydatne polecenia, podają one PID polecenia.
$ pidof nautilus
5668
$ pgrep nautilus
5668
Polecenie pgrep uruchomione z parametrem -l, wyświetla nazwę programu i PID, a z parametrami -u nazwa użytkownika, -G nazwa grupy wyświetla procesy należące do danego użytkownika lub grupy.
$ kill `pidof mplayer`
W powyższym przykładzie wykorzystałem pidof do zamknięcia mplayera nieznając jego numeru PID.


9. renice
Polecenie to zmienia priorytet procesu, najwyższy priorytet to -20, najniższy to 19. Priorytety zmniejszać może tylko root.
$ renice 19 `pidof top`
12344: old priority 0, new priority 19
Parametr -u nazwa użytkownika zmieni priorytet wszystkim procesom których właścicielem jest podany użytkownik, -g nazwa grupy podana grupa.
$ renice 5 -u adam
1000: old priority 2, new priority 5