Коротко про процеси в Linux

Трохи теорії

Вперше поняття “процес” з’явилося в операційній системі Multics — одній з перших систем з поділом часу. Процес — програма, що виконується і якій виділено процесорний час. Сама по собі програма процесом не є.

Кілька процесів можуть використовувати одну програму або ті ж ресурси типу відкритих файлів або адресного простору.

У процеси входять сегменти даних, в яких є такі змінні: 

  • набір ресурсів (відкриті файли та сигнали, які очікують обробки); 
  • адресний простір;
  • кількість потоків виконання.

Потоки виконання здійснюють операції всередині процесу. У них є лічильник команд, стек їх виконання і набір регістрів. Ядро системи працює з потоками, а не з процесами. 

Для роботи процесів потрібні 2 віртуальних ресурси: процесор і пам’ять. Перший змушує процес думати, що він використовує всю систему, а друга — що всю фізичну пам’ять. Потоки користуються однією на всіх віртуальною пам’яттю, а віртуальні процесори можуть створюватися на кожен з них.

Щоб описати роботу процесу, є кілька моделей. Найпростіша складається з 3 стадій:

  • виконання: активна стадія, коли у процесу є всі ресурси та він виконується;
  • очікування: пасивна стадія, коли процес не виконується без потрібної події, наприклад, введення даних;
  • готовність: пасивна стадія, при якій процес не виконується через незалежні від нього зовнішні причини.

Є модель складніше, в якій станів вже 5. Нові — народження і смерть процесу:

  • народження: пасивний стан, при якому самого процесу немає, але вже формується структура під його діяльність;
  • смерть: пасивний стан, коли процесу вже немає, але його структура ще є в списку; такі процеси називаються зомбі.

Які дії можуть відбуватися з процесами?

  • створення: перехід від народження до готовності;
  • знищення: від виконання до смерті;
  • відновлення: від готовності до виконання;
  • зміна пріоритету: від виконання до готовності;
  • блокування: від виконання до очікування;
  • пробудження: від очікування до готовності;
  • запуск або вибір: від готовності до виконання.

Що потрібно системі для створення процесу?

  • дати процесу ім’я;
  • внести дані про процес в загальний список;
  • призначити процесу пріоритет;
  • створити блок управління ним;
  • виділити процесу ресурси.

Як живе процес?

Створення процесу

Процеси завжди створюються якимось іншим процесом: вони діляться на батьківські (parent) і дочірні (child). У всіх процесів є параметри PID (Process ID — ідентифікатор) і PPID (Parent Process ID — ідентифікатор батьківського процесу).

У Linux процес створюється через системний виклик fork(): він повністю копіює батьківський процес і робить дочірній. Той, що породжує залишиться активним, а породжений починає працювати з місця повернення з системного виклику.

Далі вони вибудовуються в деревоподібну структуру на чолі з процесом init (PID=1). Наступний за ним процес — fork(2). Він повністю ідентичний init(1), але повертає йому свій PID і бере собі значення 0, а PPID змінюється на PID батька. За системними ресурсами батько і дитина теж ідентичні, але це не зовсім так для пам’яті.

У Linux працює функція copy-on-write. Сторінки пам’яті доступні батьківському і дочірньому процесу в режимі read-only. Якщо якийсь із процесів змінює дані на сторінці пам’яті, створюється копія сторінки, в якій ці зміни й відбуваються. Незмінена сторінка прив’язується до протилежного процесу і переходить в статус read-write.

Готовність процесу

Як тільки fork(2) виконається, процес переходить в статус “готовий”. Він очікує своєї черги, поки планувальник не виділить йому час в процесорі.

Щоб ресурси пропорційно і пріоритетно виділялися на кожен процес, в системі є планувальник процесів. Коли закінчиться квант часу процесу, що виконується,  планувальник переведе наш процес зі стадії готовності в стадію виконання.

Виконання процесу

І ось планувальник виділив процесу квант часу. Статус зміниться на “виконується”. Процесор працює з ним або весь квант часу або частину часу, яку буде працювати з іншим процесом, якщо ви скористаєтеся системним викликом sched_yield.

Очікування процесу

Припустимо, процесу потрібне введення даних для роботи або, навпаки, необхідно їх вивести. На цьому моменті він перейде в стадію очікування. Після того як ви зробите ключову дію, процес перейде в стадію готовності.

У процесу Linux є такий варіант очікування, в якому він стає нечутливим до сигналів переривання. Поки процес не вийде з очікування, всі сигнали, що надходять, стануть в чергу. Ядро Linux самостійно вибирає в яке “очікування” перевести процес. 

Зупинка процесу

Якщо вам потрібно призупинити процес, це можна зробити через сигнал SIGSTOP. Після цього він перейде в очікування і не вийде з цього стану, поки не отримає сигнал SIGCONT (відновити роботу) або SIGKILL (померти). До цього інші сигнали стануть в чергу.

Завершення процесу

Процеси не закінчуються самі по собі, а роблять запит системі через системний виклик _exit. Або система завершить їх через помилки. Якщо повернути число з функції main(), все одно спрацює виклик _exit. Хоч аргумент виклику прийме значення int, як код повернення буде використаний менший байт числа.

Процеси-зомбі

Якщо процес завершився, ядро системи фіксує дані про це і робить його “зомбі”. Це стан, коли процес помер, але пам’ять про нього залишилася в ядрі. А ще “зомбі” ігнорує SIGKILL: те, що мертве, померти не може.

Забуття процесу

Тепер нам потрібно забрати інформацію про процес-зомбі з ядра системи через спеціальні системні виклики, але зараз не про них. Цю інформацію можна втиснути в дані типу int. Щоб отримати код повернення і відомості про причини завершення процесу, потрібно використовувати макроси зі станиці man waitpid(2).

Іноді батьківський процес завершується раніше, ніж дочірній. Батьком в цій ситуації стане init, який скористається викликом wait(2) в потрібний час.

Коли батько забере інформацію про смерть дочірнього процесу, ядро зітре інформацію про дитину, а замість нього з’явиться інший процес.

Висновок

Зрозуміло, що далеко не всім потрібна інформація про те, як працює ядро їхньої  операційної системи. Але щоб розуміти інструмент, з яким ти працюєш кожен день, потрібно знати всі нюанси його пристрою. А по-іншому – ніяк.

Залишити відповідь

Дякуємо, що поділились