Лінус Торвальдс (torvalds@cs.helsinki.fi)
Вт, 6 серпня 1996 12:47:31 +0300 (EET DST)
Повідомлення, відсортовані за: [дата] [тема] [тема] [автор]
Наступне повідомлення: Бернд П. Зіллер: "Re: На жаль, у get_hash_table"
Попереднє повідомлення: Лінус Торвальдс: "Re: замовлення вводу / виводу"
У понеділок, 5 серпня 1996 р., Петро П. Ейзерлох написав:
Нам потрібно дотримуватися чіткого поняття ниток. Занадто багато людей, схоже, плутають нитку з процесом. Наступне обговорення не відображає поточний стан linux, а скоріше є спробою залишитися на дискусії високого рівня.
НІ!
Немає підстав думати, що "потоки" та "процеси" - це окремі сутності. Ось як це робиться традиційно, але я особисто вважаю, що головна помилка мислити саме так. Єдина причина вважати це - історичний багаж.
І потоки, і процеси - це лише одне: "контекст виконання". Спроба штучно розрізнити різні випадки - це лише обмежує себе.
"Контекст виконання", який називається РЄ, - це лише конгломерат всього стану цієї РЄ. Цей стан включає такі речі, як стан процесора (регістри тощо), стан MMU (відображення сторінок), стан дозволу (uid, gid) та різні "стани зв'язку" (відкриті файли, обробники сигналів тощо). Традиційно різниця між "потоком" і "процесом" полягала в основному в тому, що потоки мають стан процесора (+ можливо, якийсь інший мінімальний стан), тоді як увесь інший контекст походить від процесу. Однак це лише
одне способів розподілу загального стану РЄ, і немає нічого, що говорить про те, що це правильно зробити. Обмежувати себе таким образом просто нерозумно.
Те, як Linux думає про це (і те, як я хочу, щоб справи працювали), полягає в тому, що не існує такого поняття, як "процес" чи "потік". Існує лише сукупність COE (Linux називається "завдання"). Різні РЄ можуть ділитися частинами свого контексту між собою та одним підмножиною цього спільного доступу - це традиційна настройка «потоку» / «процесу», але це дійсно слід розглядати як ТІЛЬКІ підмножини (це важливий підмножина, але ця важливість приходить не від дизайну, а від стандартів: ми явно хочемо запускати програми, що відповідають стандартам, і поверх Linux).
Коротше кажучи: НЕ розробляйте навколо нитки / процесу мислення. Ядро повинно бути розроблене навколо способу мислення COE, а потім бібліотеки pthreads може експортувати обмежений інтерфейс pthreads для користувачів, які хочуть використовувати такий спосіб перегляду COE.
Як приклад того, що стає можливим, коли ви думаєте, що COE на відміну від потоку / процесу:
- Ви можете зробити зовнішню програму "cd", що традиційно неможливо в UNIX та / або обробити / потоком (дурний приклад, але ідея полягає в тому, що ви можете мати такі "модулі", які не обмежуються традиційним UNIX / налаштування ниток). Зробіть:
клон (CLONE_VM | CLONE_FS);
дитина: execve ("зовнішній-cd");
/ * "execve ()" роз'єднає VM, тому єдиною причиною, за якою ми використовували CLONE_VM, було швидше зробити акт клонування * /
- Ви можете зробити "vfork ()" природно (це вимагає мінімальної підтримки ядра, але ця ідеально відповідає способу мислення CUA):
клон (CLONE_VM);
дитина: продовжуйте бігати, врешті виконайте ()
мати: чекай execve
- ви можете виконувати зовнішні "IO deamons":
клон (CLONE_FILES);
дитина: відкриті дескриптори файлів тощо
мати: використовуйте фд, дитина відкрила і vv.
Все вищезазначене працює тому, що ви не прив'язані до нитки / процесу мислення. Придумайте, наприклад, веб-сервер, де сценарії CGI виконуються як "потоки виконання". Ви не можете цього зробити з традиційними потоками, тому що традиційні потоки завжди мають розділяти весь адресний простір, тож вам доведеться зв’язати все, що коли-небудь хотіли зробити на самому веб-сервері ("нитка" не може працювати інший виконуваний файл).
Думаючи про це , як «контексті виконання» проблеми , а ваші завдання тепер можуть вибрати для виконання зовнішніх програм (= відокремити адресний простір від батька) і т.д. , якщо вони хочуть, або вони можуть, наприклад , ділити все з батьком , за винятком для дескриптори файлів (так що суб-"потоки" можуть відкривати безліч файлів, не вимагаючи того, щоб батьки про них турбувалися: вони закриваються автоматично, коли під-"потік" виходить, і він не використовує файли fd's у батьківській) .
Придумайте, наприклад, різьбовий "inetd". Ви хочете з низькими накладними fork + exec, тому за допомогою способу Linux ви можете замість того, щоб використовувати "fork ()", ви пишете багатопотоковий inetd, де кожен потік створюється просто CLONE_VM (спільний адресний простір, але не діліться файлом дескриптори тощо). Тоді дитина може виконати, якщо це була зовнішня послуга (наприклад, rlogind), або, можливо, це була одна із внутрішніх служб inetd (ехо, timeofday), і в цьому випадку вона просто робить це і спрацьовує.
Ви не можете зробити це за допомогою "thread" / "process".
Лінус