- •9.3. Створення процесів
- •Базові поняття процесів і потоків
- •1.1. Процеси і потоки в сучасних ос
- •1.2. Моделі процесів і потоків
- •1.3. Складові елементи процесів і потоків
- •2. Багатопотоковість та її реалізація
- •2.1. Поняття паралелізму
- •2.2. Види паралелізму
- •2.4. Способи реалізації моделі потоків
- •2.3. Переваги і недоліки багато потоковості
- •3. Стани процесів і потоків
- •4. Опис процесів і потоків
- •4.1. Керуючі блоки процесів і потоків
- •4.2. Образи процесу і потоку
- •5. Перемикання контексту й обробка переривань
- •5.1. Організація перемикання контексту
- •5.2. Обробка переривань
- •6. Створення і завершення процесів і потоків
- •6.1. Створення процесів
- •6.2. Ієрархія процесів
- •6.3. Керування адресним простором під час створення процесів
- •6.4. Особливості завершення процесів
- •6.5. Синхронне й асинхронне виконання процесів
- •6.6. Створення і завершення потоків
- •7. Керування процесами в unix і Linux
- •7.1. Образ процесу
- •7.2. Ідентифікаційна інформація та атрибути безпеки процесу
- •7.3. Керуючий блок процесу
- •7.5. Завершення процесу
- •7.7. Запуск програми
- •7.8. Очікування завершення процесу
- •7.9. Сигнали
- •8. Керування потоками в Linux
- •8.1. Базова підтримка багато потоковості
- •8.2. Особливості нової реалізації багато потоковості в ядрі Linux
- •8.3. Потоки ядра Linux
- •8.4. Програмний інтерфейс керування потоками posix
- •9. Керування процесами у Windows хр
- •9.1. Складові елементи процесу
- •9.2. Структури даних процесу
- •9.3. Створення процесів
- •9.4. Завершення процесів
- •9.5. Процеси і ресурси. Таблиця об’єктів процесу
- •9.6. Програмний інтерфейс керування процесами Win32 арі
- •10. Керування потоками у Windows хр
- •10.1. Складові елементи потоку
- •10.2. Структури даних потоку
- •10.3. Створення потоків
- •10.4. Особливості програмного інтерфейсу потоків
- •Висновки
- •Контрольні запитання та завдання
8. Керування потоками в Linux
8.1. Базова підтримка багато потоковості
Донедавна єдиним засобом підтримки багатопотоковості в ядрі Linux був системний виклик clone( ), який дає можливість створити новий процес на базі наявного. Цей виклик багато в чому схожий на виклик fork( ), але має кілька особливостей.
♦ Для нового процесу потрібно задати спеціальний набір прапорців, що визначають, як будуть розподілятися ресурси між предком і нащадком. До ресурсів, які можна розділяти, належать адресний простір, інформація про відкриті файли, оброблювачі сигналів. Зазначимо, що у традиційній реалізації clone( ) відсутнє спільне використання ідентифікатора процесу (pid), ідентифікатора предка та деяких інших важливих атрибутів.
♦ Для нового процесу потрібно задати новий стек (оскільки внаслідок виклику clone( ) два процеси можуть спільно використовувати загальну пам’ять, для них неприпустиме використання загального стека).
Підтримка clone ( ) означає реалізацію багатопотоковості за схемою 1:1. При цьому первинними в системі є процеси, а не потоки (у Linux послідовності інструкцій процесора, з якими працює ядро, називають процесами, а не потоками ядра).
Традиційна реалізація багатопотоковості в Linux визначає, що потоки користувача відображаються на процеси в ядрі. Тому недоцільно розглядати окремо структури даних потоку в Linux — він відображається такою ж самою структурою task_struct, як і процес.
Бібліотека підтримки потоків LinuxThreads
Безпосередньо використовувати системний виклик clone( ) для створення багатопотокових застосувань складно. Крім того, таке використання веде до втрати здатності до перенесення застосувань (виклик cl one() реалізований тільки в Linux і не є частиною POSIX). Для того щоб прикладний програміст міг використати у своїх програмах потоки POSIX, необхідна реалізація цього стандарту в бібліотеці підтримки потоків.
Основною бібліотекою підтримки потоків у Linux довгий час була бібліотека LinuxThreads. У ній підтримуються ті можливості стандарту POSIX.lb, які реалізуються на основі виклику clone( ). На жаль, через обмеженість цього виклику бібліотеці властиві об’єктивні недоліки, які ми розглянемо докладно.
Недоліки традиційної підтримки багатопотоковості в Linux
Основи підтримки багатопотоковості в ядрі Linux не зазнали принципових змін від появи системного виклику clone( ). За цей час Linux із експериментальної системи перетворився на систему промислового рівня, в якій виконують корпоративні застосування в цілодобовому режимі з великим навантаженням.
Таке використання системи висунуло до реалізації багатопотоковості вимоги високої надійності та масштабованості. Стало очевидно, що реалізація, заснована на системному виклику clone( ), цим вимогам не відповідає. Назвемо деякі причини цієї невідповідності.
♦ Оскільки потоки, створені за допомогою clone( ), фактично були процесами, що спільно використовують ресурси, створення кожного потоку збільшувало кількість процесів у системі.
♦ Кожний потік у системі, будучи за своєю суттю процесом, мав власний ідентифікатор процесу (pid), що не відповідало стандарту POSIX. Крім того, якщо потік створював інший потік, між ними виникав зв’язок «предок-нащадок», тоді як всі потоки мають бути рівноправними.
♦ Кожне багатопотокове застосування користувача обов’язково створювало додатковий потік (потік-менеджер), який відповідав за створення та знищення потоків і перенаправляв їм сигнали. Наявність такого потоку знижувала надійність і масштабованість системи (наприклад, у разі аварійного завершення потоку-менеджера застосування залишалося у невизначеному стані).
Усі ці фактори робили багатопотоковість у Linux швидше цікавим полем для експериментів, аніж реальним засобом підвищення продуктивності й масштабованості застосувань. Розв’язати всі проблеми шляхом усунення недоліків clone( ) і LinuxThreads виявилося неможливим, потрібне було повне перероблення засобів реалізації багатопотоковості в ядрі та створення нової бібліотеки підтримки потоків.
