Коли лідер сеансу (оболонка) завершується, її групи процесів виявляються в складній ситуації. Якщо вони активно працюють, то позбавляються можливості використовувати стандартні потоки stdin і stdout. оскільки термінал закритий. Якщо вони припинені, то ймовірно, ніколи не будуть запущені знову, оскільки користувач терміналу не має можливості перезапустити їх, до того ж те, що вони не можуть бути запущені, означає також, що вони не можуть бути і перервані.
У цій ситуації кожна така група процесів отримує назву висячої (orphaned). Стандарт POSIX визначає її як групу процесів, чий батько є також членом цієї групи або не є членом сеансу цієї групи. Іншими словами, група процесів не є висячої до тих пір, поки у неї є батьківський процес, що належить тому ж сеансу, але іншій групі.
Хоча обидва визначення виглядають складними, концепція досить проста. Якщо група процесів припинена, і не існує процесу, який би змусив її поновитися, то ця група стає висячої [33].
Коли завершує роботу командна оболонка, все її дочірні процеси стають дочірніми по відношенню до процесу init, залишаючись при цьому в своїх вихідних сеансах. Припускаючи, що всі програми в сеансі є нащадками оболонки, все групи процесів цього сеансу стають висячими [34]. Коли група процесів перетворюється в висячу, кожен процес цієї групи отримує сигнал SIGHUP. що зазвичай перериває програму.
Програми, що не перериваються по сигналу SIGHUP. отримують сигнал SIGCONT. який продовжує виконання припинених процесів. Така послідовність перериває більшість процесів і забезпечує залишилися можливість працювати (тобто гарантує, що вони не буде в загальмованому стані) [35].
Як тільки процес стає висячим, він примусово відключається від свого керуючого терміналу (дозволяючи новому користувачеві при необхідності застосовувати цей термінал). Якщо продовжують працювати програми намагаються отримати доступ до терміналу, ці спроби викликають помилки, які встановлюють errno в значення EIO. Процеси залишаються в тому ж сеансі, і ідентифікатор сеансу не використовується для нових ідентифікаторів процесів до тих пір, поки не завершаться всі процеси даного сеансу.
10.7. Введення в ladsh
Щоб допомогти проілюструвати ідеї, обговорювані в нашій книзі, протягом наступних розділів книги ми розробимо підмножина командної оболонки Unix. В кінцевому підсумку наша оболонка буде підтримувати таке.
• Прості вбудовані команди.
• Запуск зовнішніх команд.
• Перенаправлення вводу-виводу (>. | І так далі).
Повний вихідний текст остаточної версії цієї оболонки, ladsh4.с. представлений в додатку Б. У міру додавання в ladsh нових засобів, зміни початкового тексту описуються в тексті книги. Щоб зменшити кількість змін, які ми вносимо між версіями, деякі ранні версії кілька більш складні, ніж було б потрібно. Ці невеликі ускладнення, однак, далі в книзі спрощують розробку оболонки, тому будьте терплячі. Просто поки повірте, що ці фрагменти коду необхідні; всі вони будуть пояснені пізніше.
10.7.1. Запуск зовнішніх програм за допомогою ladsh
Ось перша (і найпростіша) версія ladsh. звана ladsh1.
3: #include
4: #include
5: #include
6: #include
7: #include
8: #include
9: #include
10: #include
11: #include
12: #include
14: #define MAX_COMMAND_LEN 250 / * максимальна довжина окремої
15: командного рядка * /
16: #define JOB_STATUS_FORMAT "[.]% - 22s% .40s \ n"
18: struct jobSet
19: struct job * head; / * Заголовок списку запущених завдань * /
20: struct job * fg; / * Поточне завдання переднього плану * /
23: struct childProgram
24: pid_t Pid; / * 0 на виході * /
25: char ** argv; / * Ім'я програми з аргументами * /
29: int job Id; / * Номер завдання * /
30: int numProgs; / * Загальна кількість програм в завданні * /
31: int runningProgs; / * Кількість працюючих програм * /
32: char * text; / * Ім'я завдання * /
33: char * cmdBuf; / * Буфер різних argv * /
34: pid_t pgrp; / * Ідентифікатор групи процесів завдання * /
35: struct childProgram * progs; / * Масив програм в завданні * /
36: struct job * next; / * Для стеження за фоновими програмами * /
39: void freeJob (struct job * cmd)
42: for (i = 0; i 43: free (cmd-> progs [i] .argv); Але, може бути, не відразу. Може існувати група процесів, що містить процеси, чиї батьки ставляться до іншої групи в тому ж сеансі. Оскільки відносини "батьківський-дочірній" між процесами утворюють дерево, іноді може виявитися, що існує група процесів, яка містить тільки ті процеси, чиїм батьком є оболонка, і коли така група процесів завершується, інша стає висячої. Обговорення стане більш зрозумілим після того, як ви прочитаєте розділи, присвячені сигналам (глава 12) і управління завданнями (глава 15).Схожі статті