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); -l 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.