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