Основная причина использования процессов заключается в том, что процесс может завершиться сбоем или сойти с ума, а ОС ограничит влияние, которое это оказывает на другие процессы. Так, например, Firefox недавно начал запускать плагины в отдельных процессах, IIRC Chrome запускает разные страницы в разных процессах, а веб-серверы долгое время обрабатывали отдельные запросы в отдельных процессах.
Существует несколько различных способов применения ограничений ОС:
- Сбои - как вы заметили, если поток падает, он обычно останавливает весь процесс. Это мотивирует границы процессов браузера: браузеры и плагины браузера представляют собой сложные фрагменты кода, подверженные постоянной атаке, поэтому имеет смысл принять необычные меры предосторожности.
- Лимиты ресурсов. Если поток в вашем процессе открывает много файлов, выделяет много памяти и т. Д., То это влияет на вас. Другой процесс не нужен, потому что он может быть ограничен отдельно. Таким образом, каждый запрос на веб-сервере может быть более ограниченным в использовании ресурсов, чем сервер в целом, потому что вы хотите, чтобы ваш сервер обслуживал несколько запросов одновременно без какого-либо одного удаленного пользователя, занимающего ресурсы.
- Возможности. Зависит от ОС, но, например, вы можете запустить процесс в изолированной тюрьме, чтобы убедиться, что он не изменяет и не читает файлы, которые не должны, независимо от того, насколько уязвим ваш код для эксплойтов. В другом примере SymbianOS имеет явный список разрешений для различных действий с системой («чтение телефонной книги пользователя», «запись телефонной книги пользователя», «расшифровка файлов DRM» и т. Д.). Нет способа отменить разрешения, которые есть у вашего процесса, поэтому, если вы хотите сделать что-то очень чувствительное, а затем вернуться к режиму с низкой чувствительностью, вам понадобится где-нибудь граница процесса. Одной из причин этого является безопасность - неизвестный код или код, который может содержать недостатки безопасности, может быть несколько помещен в «песочницу», а меньшее количество кода, которое не ограничено, может быть подвергнуто более тщательному анализу. Другая причина заключается в том, что операционная система обеспечивает выполнение определенных аспектов вашего проекта.
- Драйверы. В общем случае драйвер устройства управляет общим доступом к уникальному системному ресурсу. Как и в случае с возможностями, ограничение этого доступа одним процессом драйвера означает, что вы можете запретить его всем остальным процессам. Например, IIRC TrueCrypt в Windows устанавливает драйвер с расширенными разрешениями, которые позволяют ему регистрировать зашифрованный контейнер с буквой диска, а затем действовать как любая другая файловая система Windows. Графическая часть приложения работает в обычном пользовательском режиме. Я не уверен, что драйверы файловой системы в Windows действительно нуждаются в связанном процессе, но драйверы устройств в целом могут подойти, поэтому, даже если это не хороший пример, надеюсь, это даст идею.
Еще одна потенциальная причина использования процессов заключается в том, что это упрощает анализ вашего кода. В многопоточном коде вы полагаетесь на инварианты всех ваших классов, чтобы сделать вывод, что доступ к определенному объекту сериализован: если ваш код не многопоточный, то вы знаете, , что это [*]. Конечно, это можно сделать и с многопоточным кодом, просто убедитесь, что вы знаете, какой поток «владеет» каждым объектом, и никогда не обращаетесь к объекту из потока, который не является его владельцем. Границы процесса усиливают это, а не просто проектируют для этого. Опять же, не уверен, что это мотивация, но, например, клиент World Community Grid может использовать несколько ядер. В этом режиме он запускает несколько процессов с совершенно разными задачами в каждом, поэтому он имеет преимущества в производительности дополнительных ядер без необходимости параллелизации какой-либо отдельной задачи или кода для любой задачи, которая должна быть поточно-ориентированной.
[*] хорошо, если он не был создан в общей памяти. Вам также необходимо избегать неожиданных рекурсивных вызовов и тому подобного, но обычно это более простая проблема, чем синхронизация многопоточного кода.