Procesy — komendy

ps — wyświetla informacje o stanie procesów. Bez żadnych flag — wyświetla informacje o procesach uruchomionych z danego terminala w skróconej formie (przykład 1), z flagami: -e wypisuje informacje o wszystkich procesach w systemie (przykład 2); -f wyświetla pełną informację o procesach (przykład 3);            -wyświetla długą informację o procesach (przykład 4); -t wypisuje informacje o procesach skojarzonych z określonym terminalem; -p wypisuje informacje o procesach z podanym numerem PID; -u wypisuje tylko procesy z podanym numerem UID lub nazwą użytkownika. Niżej podano przykłady wykorzystania komendy ps z różnymi flagami. Proszę zwrócić szczególną uwagę na pierwszy przykład.

> ps | more

   PID    TTY  TIME CMD

 19892  pts/4  0:02 -tcsh

 20069  pts/4  0:00 ps

 31078  pts/4  0:00 more

> ps -e | more

   PID    TTY  TIME CMD

     1      -  9:14 init

  2474      -  0:07 timed

  2597      -  4:28 syncd

  2956      -  0:00 srcmstr

  3207      -  6:12 upsd

  3623      -  0:00 errdemon

  3993      -  0:07 sendmail

   ...

 26249  pts/4  0:00 more

 26876  pts/6  0:00 csh

 26903  pts/6  0:00 more

 31082      -  0:02 sshd

> ps -ef | more

    USER   PID  PPID   C    STIME    TTY  TIME CMD

    root     1     0   0   Nov 12      -  9:15 /etc/init

    root  2474  2956   0   Nov 12      -  0:07 /etc/timed -S -M

     ...

   danda 21172 19892  15 11:06:32  pts/4  0:00 ps -ef

   danda 21685 19892   6 11:06:32  pts/4  0:00 more

    root 24315  5794   0 10:27:17      -  0:00 telnetd

    root 24755  5794   0 10:20:50      -  0:01 telnetd

  jfuksa 25131  5794   0 10:59:33      -  0:00 ftpd

  pacyna 26876 24315   0 10:27:17  pts/6  0:01 -csh

    root 31082  6577   0 11:02:47      -  0:13 /usr/bin/sshd

> ps -l

       F S UID   PID  PPID   C PRI NI ADDR    SZ    WCHAN    TTY  TIME CMD

  241c01 S 949 19892 24755   1  60 20 1789   328           pts/4  0:02 tcsh

  200001 R 949 29345 19892  16  68 20 2512   120           pts/4  0:00 ps

Znaczenia nagłówków: PID — identyfikator procesu, TTY — terminal, TIME — czas wykonywania procesu w minutach i sekundach, CMD — komenda skojarzona z procesem, USER — użytkownik, PPID — PID procesu rodzica, C — wykorzystanie CPU przez proces, STIME — czas rozpoczęcia procesu, F — znaczniki procesu, S — stan procesu, UID — id użytkownika, PRI — priorytet procesu (im większa liczba tym niższy priorytet), NI — „nice”, wartość wykorzystywana przy ustalaniu priorytetu, ADDR — adres procesu w pamięci, WCHAN — zdarzenie, na jakie oczekuje proces.

Proszę znaleźć proces, który jest ojcem bieżącego shella (za pomocą komendy ps –f), a następnie znaleźć jego ojca (np. za pomocą komendy grep) itd., aż do procesu, który nie ma PPID.

kill — wysyła sygnały do procesu. Kill z flagą -l wyświetla listę sygnałów, jakie mogą być wysłane do procesu. Najczęściej wykorzystywane jest polecenie kill -9 NR_PID, usuwające proces o podanym PID. Sygnał może być zapisany w postaci symbolicznej lub numerycznej. Postać numeryczna odpowiada pozycji sygnału w postaci symbolicznej na liście po wywołaniu komendy kill -l. Niektóre sygnały można wywoływać w inny sposób: np. polecenie kill -3 NR_PID (czyli kill -QUIT NR_PID) można wywołać z pomocą CTRL+”\”, zaś polecenie kill -2 NR_PID (czyli kill -INT NR_PID) można wywołać z pomocą CTRL+”C”. Programy napisane w C lub skrypty mogą być odporne na niektóre sygnały (np. more jest odporny na QUIT), ale żaden proces nie jest odporny na polecenie kill -9 NR_PID (kill -KILL NR_PID). W przykładzie poniżej terminal po prawej stronie służy do wywoływania komendy kill, zaś terminal po lewej stronie — do uruchamiania procesów, na których operuje komenda kill.

> ps -e | more

   PID    TTY  TIME CMD

     1      -  9:38 init

  2474      -  0:07 timed

  2597      -  4:41 syncd

  ...

    6055      -  6:04 named

  7100 pts/12  0:01 tcsh

  7358      -  0:18 ypserv

  7616      -  0:06 ypbind

  7897      -  0:02 biod

  8132      -  0:02 biod

--More—Killed

>

> ps -u username

 UID   PID    TTY  TIME CMD

 949 19795  pts/9  0:03 tcsh

 949 20939  pts/9  0:00 more

 949 24237 pts/11  0:02 tcsh

 949 24525 pts/11  0:00 ps

> kill -9 20939

> vi status

ok.

~

~

...

~

"status" 1 line, 3 characters

Killed

~     >

> ps -u username

UID   PID    TTY  TIME CMD

 949 19795  pts/9  0:03 tcsh

 949 24237 pts/11  0:02 tcsh

 949 30717  pts/9  0:00 vi

 949 31506 pts/11  0:00 ps

> kill -2 30717

> kill -3 30717

> kill -9 30717

> kill -l

HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP

TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ MSG WINCH PWR USR1 USR2 PROF DANGER

VTALRM MIGRATE PRE GRANT RETRACT SOUND SAK

W drugim przykładzie widać, że vi nie zareagował ani na sygnał INT, ani na QUIT. Dopiero sygnał KILL zakończył jego działanie.

Jednym z ważniejszych sygnałów jest także sygnał TERM (terminate), czyli programowy sygnał narzucający zakończenie procesu. Procesy mogą być odporne na ten sygnał (np. vi).

Uwaga: kill -9 0, kill -9 -1.

nohup — polecenie pozwalające na wykonywanie procesu po wyjściu użytkownika z systemu, użyteczne na przykład w przypadku ściągania danych z serwera ftp lub wykonywania czasochłonnych obliczeń. Poniżej przedstawiono przykład (plik przyklad), w którym do kalkulatora bc przekazywane są polecenia z pliku val, zaś wynik ma być umieszczony w pliku o nazwie wynik już po opuszczeniu systemu przez użytkownika. Po lewej stronie wyświetlono zawartość pliku przyklad oraz pliku pomocniczego czy_wynik, czyli skryptu wyświetlającego pierwszą linię pliku wynik. W ten sposób skrypt czy_wynik sprawdza, czy obliczenia nie zostały wykonane przed wylogowaniem z systemu.

> cat przyklad

nohup bc < val > wynik &

> cat czy_wynik

#!/bin/sh

STATUS=ok

echo $STATUS

while test $STATUS -eq "ok"

 do

  head -1 wynik

  sleep 2

 done

> chmod u+x czy_wynik

> chmod u+x przyklad

> ls wynik

ls: 0653-341 The file wynik does not exist.

> ./czy_wynik &

...

> ./przyklad &

...

> logout

Po ponownym wejściu do systemu widać, że został utworzony plik o nazwie wynik. Powyższy przykład najlepiej wykonać na dwóch oknach telnet’a — w jednym uruchamiając plik przyklad, zaś w drugim — plik sprawdzający czy_wynik.

Lepszy przykład to:

> nohup sleep 300 &

> logout

 

 

login

> ps -u loginname

Po ps -u wypisze proces sleep 300 uruchomiony przed wylogowaniem z systemu.

vmstat  — pole sy pokazuje ilość wywołań funkcji systemowych w ciągu okresu próbkowania, pole cs pokazuje ilość przełączeń kontekstu w ciągu okresu próbkowania, pole us - procent czasu spędzony przez system w trybie użytkownika, pole sy - procent czasu systemu w trybie jądra, pole id - procent czasu, gdy system nie wykonywał nic.

Komendy przydatne dla procesów wykonywanych „w tle” i zawieszonych

Do operacji na procesach zawieszonych lub wykonywanych „w tle” przydatne są komendy: jobs, fg i bg. Za pomocą komend jobs i bg można wyświetlić procesy wykonywane „w tle” i zawieszone. Za pomocą komendy fg możliwe jest uruchomienie zawieszonego procesu lub przekazanie standardowego wejścia i wyjścia procesowi wykonującemu się „w tle”. Przykłady wykorzystania ww. komend zamieszczono poniżej.

> cat val

23909064562346512675461245123451345^100

> cat val1

238000909064562346512675461212145123451345^100

> bc < val &

[1] 21882

> bc < val1 &

[2] 19582

> jobs

[1]  + Running                bc < val

[2]  - Running                bc < val1

> bg

[1]    bc < val &

> fg [2]

bc < val1

 

 


Funkcje użytkownika i funkcje systemu — program

W przykładzie poniżej przedstawiono program, który obrazuje różnicę między czasem wykonywania funkcji systemowych i funkcji użytkownika. W lewym oknie znajduje się przykład programu wykorzystującego funkcje systemowe (czytanie znaków z pliku do bufora), zaś w prawym oknie zaprezentowano wykorzystanie programu.

Czas spędzony w trybie jądra jest w pewnym stopniu proporcjonalny do ilości wywołań funkcji systemowej read. Jeżeli dane będą wczytywane do dużego bufora, to cały plik tekstowy można odczytać za pomocą kilku wywołań funkcji read (pętla while wykona jedynie kilka „obiegów”). Natomiast jeśli dane będą wczytywane małymi porcjami, to do przeczytania całego pliku niezbędne jest wielokrotne wywołanie funkcji systemowej, co będzie widoczne w statystyce z wykonania programu /bin/time. Wynika stąd, że rozumienie istoty funkcji systemowych przez programistę może znacznie wpłynąć na efektywność (szybkość wykonania)  programu.

 

> cat program2.c

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

 

char buf1[20000];

 

main(int argc, char *argv[])

{

  int len, i, f;

  struct stat buf;

 

  len = atoi(argv[1]);

  f = open("/usr/lpp/X11/bin/X.o", O_RDONLY);

  fstat(f, &buf);

 

  i = 0;

  while(i < buf.st_size) {

    read(f, buf1, len);

    i = i + len;

  }

  close(f);

}

> cc -o prog2 program2.c

>

> /bin/time ./syuz 34 65536

 

Real   23.2

User   2.5

System 14.3

Funkcje użytkownika (np. dodawanie w przykładzie powyżej) wykonują się znacznie szybciej, niż funkcje systemowe (np. wczytywanie danych z pliku). Plik /usr/lpp/X11/bin/X.o został wybrany celowo, ze względu na duży rozmiar. Liczba 65536 określa w programie rozmiar bloków, w których wczytywane są dane z pliku. Z przykładu wynika, że funkcje systemowe są czasochłonne, dlatego należy minimalizować ich wywołania. Jest to spowodowane tym, że funkcje systemowe nie mogą być wywłaszczone (przerwane). System musi czekać na zakończenie wykonywania funkcji systemowej. przez co rośnie ilość procesów kolejkowanych i obciążenie systemu.