Процеси, управление на задачите (Job control)

 

1.       Управление на задачите. 1

Въведение. 1

Команда  jobs. 1

Команда fg. 1

Команда bg. 1

2.       Създаване, управление и завършване (kill) на процеси. 1

Въведение. 1

Пораждащ и породен процес (Parent and Child). 1

Команда ps. 1

Команда top (table of processes)

Команда nice. 1

3.       Сигнали. 1

Въведение. 1

Някои общи сигнали. 1

Изпращане на сигнал – команда kill 1

 

 

     1.     Управление на задачите

Въведение

В Unix / Unix задача (job) представлява група процеси. Базовите средства включват стартиране, спиране, рестартиране, завършване и прехвърляне на заден план (background) на процесите. По разширени функции за управление могат да бъдат извършвани чрез подаване на сигнали към процесите.

При отварянето на терминал потребителят притежава само един процес – командния интерпретатор. Повечето задачи - например стандартната Unix команда cat  (concatenate files), се  изпълняват чрез предаване на контрола от терминала на програмата, четене от стандартния вход, писане на стандартния изход, взимане на сигнали от клавиатурата (като сигнал за край потока – „Control+D“)  и връщането на контрола на командния интерпретатор след края на програмата.

Понякога обаче потребителя иска да се изпълни някаква задача, докато използва терминала за нещо друго. Работеща задача, която не комуникира с терминала се нарича работеща на заден план (in the background), докато единствената задача комуникираща с терминала работи на преден план (in the foreground). Управлението на задачите предоставя средства за стартиране на процеси на заден план, изпращане на вече работещи процеси на заден план и обратно и прекратяване и завършване на процеси.

Понятието задача (job) се свързва с единична команда към интерпретатора, която стартира еди или повече  процеси. Процесите могат да създават допълнителни породени (child) процеси. Единична команда може да стартира конвейер от процеси.

Управлението на задачите позволява на интерпретатора да управлява тези процеси като единна единица и например да спира изпълнението на цялата група с подходяща комбинация от клавиатурата (обикновено Control+Z).

Поставянето на “&” в края на командната линия стартира задачата на заден план. Ако задачата се нуждае от входна комуникация с обвивката (например stdin), изпълнението й се спира, но тя остава активна.  Това не се отнася за  stdout -  задача работеща на заден план  продължава да извежда съобщения към терминала, от който е извикана.

С комбинацията Ctrl+Z се спира изпълнението на задача работеща на преден план и се прекратява комуникацията й с командния интерпретатор. Задачата остава активна. Нейното изпълнение може да бъде рестартирано с извеждането й отново на преден план  или с рестартирането й на заден план.

Спрените и работещите на заден план задачи получават номера на задачите в таблица на задачите.

Тези номера могат да бъдат подавани към вградените команди за управление на задачите.

Вградени команди за управление на задачите: jobs, fg, и bg

Команда  jobs

Вградената команда  jobs извежда списък на активните задачи и техните номера. Преди да бъде демонстрирана ще стартирам няколко команди на заден план (всяка команда стартира отделна задача (job)- xeyes (A Graphical eyes, which follows the mouse movement),  gnome-calculator, nano,  след което ще стартирам команда ping на преден план, след което ще я спра (Stopped) и прехвърля на заден с Ctrl+Z :

·  

$xeyes &
[1] 3622
$ gnome-calculator &
[2] 3623
$ nano test.txt &
[3] 3634
$ ping www.google.com
PING www.google.com (142.250.187.164) 56(84) bytes of data.
64 bytes from sof02s46-in-f4.1e100.net (142.250.187.164): icmp_seq=1 ttl=117 time=3.51 ms
64 bytes from sof02s46-in-f4.1e100.net (142.250.187.164): icmp_seq=2 ttl=117 time=4.65 ms
64 bytes from sof02s46-in-f4.1e100.net (142.250.187.164): icmp_seq=3 ttl=117 time=3.79 ms
64 bytes from sof02s46-in-f4.1e100.net (142.250.187.164): icmp_seq=4 ttl=117 time=4.02 ms
^Z
[3]-  Stopped                 nano test.txt
[4]+  Stopped                 ping www.google.com


$jobs
[1]   Running                 xeyes &
[2]   Running                 gnome-calculator &
[3]-  Stopped                 nano test.txt
[4]+  Stopped                 ping www.google.com


За повече информация (включваща номерата на процесите) може да се използва опцията
-l :

jobs -l
[1]   3622 Running                 xeyes &
[2]   3623 Running                 gnome-calculator &
[3]-  3634 Stopped (tty output)    nano test.txt
[4]+  3639 Stopped                 ping www.google.com
imom@imom-VirtualBox:~$

·        Номерата на задачите са указани с квадратни скоби, но когато трябва да се използват от команди fg и bg пред тях се поставя знак за процент - %, например %1.

·        Задачите отбелязани с + и –  освен с номерата си могат да бъдат използвани с  „%+“ съответно с  „%-„

o   %+ е текущата задача -  последната активна задача.

o   %- е предпоследната активна задача.

Команда fg

·        Извиква задача от заден план и я прави работеща на преден.

·        Рестартира спряна (например с Ctrl+Z ) задача на преден план .

·        fg %1“ ще изведе на преден план задача номер 1.

·        fg без параметри е еквивалентна на „fg %+“.

$  fg %+
ping www.google.com
64 bytes from ams15s29-in-f100.1e100.net (172.217.17.100): icmp_seq=4 ttl=117 time=3.23 ms
64 bytes from ams15s29-in-f100.1e100.net (172.217.17.100): icmp_seq=5 ttl=117 time=3.66 ms
64 bytes from ams15s29-in-f100.1e100.net (172.217.17.100): icmp_seq=6 ttl=117 time=5.67 ms
^Z
[4]+  Stopped                 ping www.google.com
$

$

Команда bg

·        Рестартира спряна задача, като я оставя да се изпълнява на заден план. Тя не може да комуникира с интерпретатора тъй като е на заден план, но ако няма нужда от тази комуникация се изпълнява.

·        bg без аргументи работи върху текущата задача.


$ jobs
[1]   Running                 xeyes &
[2]   Running                 gnome-calculator &
[3]+  Stopped                 nano test.txt
[4]-  Stopped                 ping www.google.com

$ fg %1
xeyes
^Z
[1]+  Stopped                 xeyes

$ jobs
[1]+  Stopped                 xeyes
[2]   Running                 gnome-calculator &
[3]-  Stopped                 nano test.txt
[4]   Stopped                 ping www.google.com

$ bg %1
[1]+ xeyes &

$ jobs
[1]   Running                 xeyes &
[2]-  Running                 gnome-calculator &
[3]+  Stopped                 nano test.txt
[4]   Stopped                 ping www.google.com
$

      В примера се извежда на преден план работещата задача на заден xeyes, стартира след което задачата се спира с Ctrl+Z. Командата  bg я рестартира, като я оставя на заден план.

     2.     Създаване, управление и завършване (kill) на процеси

Въведение

·        Ядрото разглежда всяка работеща програма като процес (running instance of a program).

·        Процесът ‘lives’ докато се изпълнява с различно време на живот.

·        Процесът умира ( ‘dies’) при завършването си.

·        Ядрото идентифицира всеки процес чрез номер – идентификатор на процес (pid). Той може да бъде проверен чрез команда pidof

$ pidof  bash
15170

$

·        Ядрото пази информация за различни свойства на всеки процес.
Процесите са свързани с контролиращия ги терминал. При затваряне на терминала се унищожават свързаните с него процеси.
Съществуват процеси, наричани демони (daemon processes),  които не са свързани с терминал и са важни за функционирането на системата. Стартират се при  първоначалното зареждане на системата и завършват при shutdown.


Пораждащ и породен процес (Parent and Child)

Всеки процес има пораждащ го процес (Parent), като може да има или няма породени от него процеси (Child).  
Нов процес се създава, когато съществуващ процес прави  точно копие на себе си в паметта. За целта се използва функцията fork() .   След нейното извикване изпълнението се разклонява в два процеса.
Новият процес има ново pid, като сьхранява и pid на породилия го процес -   ( parent process id - ppid) -  pid на процеса, който го е създал.

On the success of a fork() system call:
The Process ID (PID) of the child process is returned to the parent process.
0 is returned to the child process.

On the failure of a fork() system call,
-1 is returned to the parent process.
A child process is not created.

Новите процеси са свързани с  терминала, от който са създадени. Със затварянето на терминала те се унищожават.
Има процеси, които не са свързани терминал, които осигуряват функционирането на системата.

Пимер:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    fprintf(stdout,"printing from process_id(pid)=%d \n",getpid());
    // make two process which run same program after fork();
    pid_t p = fork();
    if(p<0){
      fprintf(stderr,"fork fail");
      exit(1);
    }
   fprintf(stdout,"after fork()!, pid = %d ppid= %d \n",getpid(),getppid());
    return 0;
}


Допълнителна информация за функцията  fork().

    o   Ядрото стартира като инициализиращ процес (init) с pid 1 при зареждане на системата.

$ pidof init

1

$

    o   Всеки друг процес е породен от pid 1

По този начин структурата на работещите процеси представлява  дървовидна структура с корен процеса init
 
Всеки процес има своя собствена работна директория, първоначално наследена от породилия го процес.

Всеки процес има обкръжение (environment) – колекция от именовани променливи на обкръжението със асоциирани стойности
Обкръжението на процеса се наследява от пораждащия го процес.
Всеки процес има идентификатор на притежаващия го потребител (user id - uid) и идентификатор на групата на потребителя (group id - gid), които заедно определят правата на процеса.
Процесите завършват чрез "_exit system call", който освобождава ресурсите заемани от тях и задава завършващия статус на процеса. Най-често статус 0 показва, че процесът е завършил нормално. Пораждащият процес обаче трябва да потвърди завършването на породения чрез "wait system call", който проверява завършващия статус.

Друг начин на завършване на процес е чрез подаване на сигнали към него (описани по-долу).

Orphan Processes - процеси, на които пораждащият ги процес е завършил преди тях. В този случай отговорността  за   "wait system call", за да може да завърши, се поема от процеса с pid 1.

Zombie Processes - процеси, които са завършили, но поради една или друга причина пораждащият ги процес не е подал
"wait system call". За да може да им бъде проверен завършващият статус ядрото ги задържа в таблицата на процесите, макар техните ресурси да са освободени. Тези процеси не могат да бъдат завършени чрез подаване на сигнали защото технически, те са завършили. Тъй като те запълват таблицата "init" процеса може да ги "осинови" и да подаде  "wait system call" за премахването им от таблицата.

Команда ps

o   Дава моментна снимка на изпълняваните процеси в даден момент от време.

o   Много гъвкава по отношение на количеството и начина на извеждане на показваната информация:

o   Използвана без опции показва късо резюме за всеки процес

o   Само процесите, които се притежават от текущия потребител и които за закачени за терминала

$ ps

  PID TTY          TIME CMD

25036 pts/8    00:00:00 bash

25471 pts/8    00:00:00 ps

$

       PID: Идентификатор на процеса
TTY: терминал свързан с процеса 
TIME: Общо използвано време от CPU 
CMD: име на командата

o   За съжаление приеманите опции не следват единен синтаксис а  представляват смес от три синтаксиса :

o   UNIX опции, които могат да бъдат групирани и се предхождат от тире.

o   BSD опции, които могат да бъдат групирани и не се предхождат от тире.

o   GNU дълги опции, които се предхождат от две тирета.

Различните опции могат свободно да бъдат смесвани, но има опасност от конфликти.


o   ps има много опции

Някои от най-често използваните :

o   a                показва процесите използвани от други потребители

o   f                 показва пораждащите процеси като дървовидна структура

$ bash

$ ps f

  PID TTY      STAT   TIME COMMAND

25036 pts/8    Ss     0:00 -bash

25528 pts/8    S      0:00  \_ bash

25538 pts/8    R+     0:00      \_ ps f

o   u                показва потребителите и кога е стартиран процеса (RSS - Resident Set Size, VSZ - Virtual Memory Size)

$ps u
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
imom     15170  0.0  0.0  25328  5404 pts/0    Ss   06:52   0:00 -bash
imom     15468  0.2  0.0  25280  5268 pts/0    S    07:34   0:00 bash
imom     15477  0.0  0.0  39812  3460 pts/0    R+   07:35   0:00 ps u
$

o   -e               показва информация за всички процеси

o   ps -e |grep ?               показва информация за всички процеси не свързани с терминал

o   -l                допълнителна информация (в „дълъг“ формат)

ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000 15170 15169  0  80   0 -  6332 wait   pts/0    00:00:00 bash
0 S  1000 15468 15170  0  80   0 -  6320 wait   pts/0    00:00:00 bash
0 R  1000 15650 15468  0  80   0 -  7839 -      pts/0    00:00:00 ps

o    -f                използва пълен (full) формат

o   -C cmd      показва само процесите с име cmd

o   -U user     показва само процесите притежавани от user

Допълнителна информация може да се намери с 

      $man ps

Състояние на процеса

Колоната STAT  показва в какво състояние се намира процеса. Най-често срещаните кодове са:

      R: running 
S: прекъсваем  sleep, чакащ някакво събитие (вход от терминал, завършване на породен процес ...)
D: непрекъсваем sleep, процесът не може да бъде killed или прекъснат чрез сигнал.
Z: Zombie
T: Stopped

В състоянието на процеса могат да се появят и допълнителни символи

       <    висок приоритет(not nice за другите потребители)
 N    нисък приоритет (nice за другите потребители)
  s    лидер на сесията
  l    процесът е multi-threaded
  +   процесът е в групата на преден план

Команда top (table of processes)

Показва на пълен екран на терминала моментна снимка на активността на процесите. Снимката се обновява автоматично през къс период от време и създава илюзия за следене в реално време.

Процесите са подредени в низходящ ред, съобразно процента използвано време на процесора.

Показва също така информация за натоварването на системата.

Позволява въвеждането на интерактивни команди в процеса на изпълнение.

Пояснение на първите редове 

       Първи ред - top

       Втори ред - Tasks  

     Трети ред - Cpu


    Четвърти и пети ред - използвана памет

     Повече по този въпрос може да се види тук

Пояснение за някои колони:

NI - Nice Value.  Отрицателна стойност означава по-висок приоритет, а положителна - по-нисък.

 RES  -  Resident Memory Size.  Подмножество на виртуалното адресно пространство (VIRT) представляващо използваната резидентна памет.

Някои опции на командния ред:

-b              Batch mode – изпраща снимките последователнона стандартния изход

-n num     завършва след показването на num снимки

-d delay   изчаква delay секунди  между снимките

-i               игнорира не ползващите ресурси (idle) процеси

-s               забранява интерактивните команди (опасни ако се използват от супер-потребителя  - superuser)

 

Интерактивни команди :

Key           Behaviour

q                Quit the program

Ctrl+L     Repaint the screen

h                Show a help screen

k                Prompts for a pid and a signal, and sends that signal to that process

n                Prompts for the number of processes to show information; 0 (the default) means to show as many as will fit

r                Change the priority (‘niceness’) of a process

s                Change the number of seconds to delay between updates. The number may include fractions of a second (0.5, for example)

Команда nice

Вградена команда, която се използва за извикване на команда или скрипт на обвивката с определен приоритет,  давайки му повече или по-малко процесорно време спрямо другите процеси. За най-висок приоритет:  -20, за най-нисък: 19. Подразбиращата  стойност се наследява от пораждащия процес и обикновено е 0.

Например ако потребител желае да компресира голям файл, но не желае да забавя другите процеси:

$ nice -n 19 tar cvzf large_archived.tgz largefile

 Опцията "c" изисква създаване на архив, опцията "v" (verbose) изисква  операцията да извежда максимално информация, а опцията "f" има за аргумент името на архивата.

Приоритетът на работещ процес може да се сменя с команда "renice".  

Usage:
 renice [-n] <priority> [-p|--pid] <pid>...
 renice [-n] <priority>  -g|--pgrp <pgid>...
 renice [-n] <priority>  -u|--user <user>...

Alter the priority of running processes.

Options:
 -n, --priority <num>   specify the nice increment value
 -p, --pid <id>         interpret argument as process ID (default)
 -g, --pgrp <id>        interpret argument as process group ID
 -u, --user <name>|<id> interpret argument as username or user ID
 

Например командата:

$  renice +1 987 -u daemon root -p 32

Сменя приоритета на процеси с pid 987 и 32,  както и на всички процеси със собственици daemon и root.

     3.     Сигнали

Въведение

Сигналите са асинхронни предупреждения за важни събития изпращани към процесите (или задачите) от ядрото или от друг процес. Всеки сигнал е цяло число (1,2, …) с мнемонично име, което обикновено е дефинирано в файла /usr/include/signal.h. Те прекъсват дейността на процеса и го принуждават да ги обработи веднага.

Имената на сигналите са с главни букви и често включват SIG в името например SIGINT

Командата “killl“ извежда списъка на наличните в системата сигнали.

Някои общи сигнали

Име                              Номер                       Действие

SIGINT (или   INT)          2          Прекъсване. Изпраща се от ядрото при въвеждане Ctrl+C на терминала.

SIGTERM (или TERM)   15        “Please terminate.” Заявка за нормално приключване на процеса.

SIGKILL  (или KILL)      9          “Die!” Принуждава процеса да завърши без да му се дава възможност за нормална завършваща дейност.

SIGSTOP (или STOP)      19        Временно спира  (suspend) действието на процеса. Изпраща се от ядрото при въвеждане Ctrl+Z на терминала.

SIGCONT (или CONT)    19      стартира отново спрян процес (resume)Временно прекратяв

SIGHUP                    1           Hang up. Изпраща се от ядрото при отписване на потребителя. Използвано от демони като инструкция за презареждане на конфигурационните файлове.

Изпращане на сигнал – команда kill

Командата изпраща сигнал към процес (не само за завършване на процес). В много ядра командата е вградена. Сигналът се подава с опция –s ( която може да бъде пропусната).

Синтаксис: kill [ -s сигнал | -ppid...  

Например сигналът  SIGTERM може да се подаде по следните начини ( pid на процеса е '1234'):

$kill 1234                

$kill -s TERM 1234

$kill -TERM 1234

$kill -15 1234

Сигналът  SIGKILL може да бъде подаден по три начина:

$kill -s KILL 1234

$kill -KILL 1234

$kill -9 1234

Могат да бъдат указани няколко pid  на процеси, към които да бъде подаден сигналът едновременно.

Пример. Ако трябва да бъде спрян  и след това рестартиран процес (или задача)  работещ в background може да се използва номерът на задачата или на процеса:

$xeyes &
[1] 9426

$ jobs -l
[1]+  9426 Running                 xeyes &

$ kill -STOP %1

$ jobs -l
[1]+  9426 Stopped (signal)        xeyes

$ kill -CONT %1
$ jobs -l
[1]+  9426 Running                 xeyes &