Какие ресурсы распределяются между потоками? - PullRequest
226 голосов
/ 19 ноября 2009

Недавно мне задали вопрос в интервью, в чем разница между процессом и потоком. Действительно, я не знал ответа. Я немного подумал и дал очень странный ответ.

Потоки разделяют одну и ту же память, процессы - нет. После ответа на это интервьюер злобно улыбнулся и задал мне следующие вопросы:

Q. Знаете ли вы сегменты, на которые программа делится?

Мой ответ: Да (думал, что это легко) Стек, Данные, Код, Куча

Q. Итак, скажите мне: какие сегменты разделены потоками?

Я не мог ответить на это и в итоге сказал все из них.

Пожалуйста, кто-нибудь может представить правильные и впечатляющие ответы на разницу между процессом и потоком?

Ответы [ 13 ]

151 голосов
/ 19 ноября 2009

Вы в значительной степени правы, но потоки разделяют все сегменты , кроме стека. Потоки имеют независимые стеки вызовов, однако память в других стеках потоков по-прежнему доступна, и теоретически вы можете хранить указатель на память в кадре локального стека другого потока (хотя вам, вероятно, следует найти лучшее место для размещения этой памяти!). 1003 *

49 голосов
/ 19 ноября 2009

Из Википедия (я думаю, это было бы действительно хорошим ответом для интервьюера: P)

Нитки отличаются от традиционных многозадачная операционная система процессы в этом:

  • процессы обычно независимы, а потоки существуют как подмножества процесс
  • процессы несут значительную информацию о состоянии, тогда как несколько потоков в состоянии общего процесса, а также как память и другие ресурсы
  • процессы имеют отдельные адресные пространства, тогда как потоки разделяют их адресное пространство
  • процессы взаимодействуют только через системный межпроцессный процесс Коммуникационные механизмы.
  • Переключение контекста между потоками в одном и том же процессе обычно происходит быстрее чем переключение контекста между процессы.
39 голосов
/ 22 октября 2013

Что действительно нужно отметить, так это то, что в этом вопросе есть два аспекта - теоретический аспект и аспект реализации.

Сначала давайте посмотрим на теоретический аспект. Вам необходимо понять, что такое концептуально процесс, чтобы понять разницу между процессом и потоком и тем, что между ними.

У нас есть следующее из раздела 2.2.2 Классическая модель потока в Современные операционные системы 3e от Tanenbaum:

Модель процесса основана на двух независимых концепциях: ресурс группировка и исполнение. Иногда полезно разделить их; это где темы вступают ....

Он продолжает:

Одним из способов рассмотрения процесса является то, что это способ группируйте связанные ресурсы вместе. Процесс имеет адресное пространство содержащий текст программы и данные, а также другие ресурсы. Эти ресурс может включать открытые файлы, дочерние процессы, ожидающие тревоги, обработчики сигналов, учетная информация и многое другое. Положив их вместе в форме процесса ими можно легче управлять. Другая концепция, которую имеет процесс, - это поток выполнения, обычно сокращен до просто нити. В потоке есть счетчик программ, который хранит отслеживать, какую инструкцию выполнять дальше. У него есть регистры, которые держать свои текущие рабочие переменные. У него есть стек, который содержит история выполнения, с одним кадром для каждой вызванной процедуры, но не пока вернулся из. Хотя поток должен выполняться в каком-то процессе, нить и ее процесс - разные понятия и могут рассматриваться отдельно. Процессы используются для группировки ресурсов; потоки являются объектами, запланированными для выполнения на ЦП.

Далее он приводит следующую таблицу:

Per process items             | Per thread items
------------------------------|-----------------
Address space                 | Program counter
Global variables              | Registers
Open files                    | Stack
Child processes               | State
Pending alarms                |
Signals and signal handlers   |
Accounting information        |

Выше указано, что нужно для работы потоков. Как уже отмечали другие, такие вещи, как сегменты, являются деталями реализации, зависящими от ОС.

27 голосов
/ 19 ноября 2009

Сообщите интервьюеру, что это полностью зависит от реализации ОС.

Взять, например, Windows x86. Есть только 2 сегментов [1], Код и Данные. И оба они сопоставлены со всем адресным пространством 2 ГБ (линейное, пользовательское) База = 0, предел = 2 ГБ. Они бы сделали один, но x86 не позволяет сегменту быть как для чтения / записи, так и для выполнения. Таким образом, они сделали два и установили CS для указания на дескриптор кода, а остальные (DS, ES, SS и т. Д.) Для указания на другой [2]. Но оба указывают на одно и то же!

Человек, опрашивающий вас, сделал скрытое предположение, что он / она не заявил, и это глупый трюк.

Так что относительно

Q. Так скажите мне, какой сегмент потока поделишься?

Сегменты не имеют отношения к вопросу, по крайней мере, в Windows. Потоки разделяют все адресное пространство. Существует только 1 сегмент стека, SS, и он указывает на те же вещи, что и DS, ES и CS [2]. То есть все кровавое пространство пользователя . 0-2GB. Конечно, это не означает, что потоки имеют только 1 стек. Естественно, у каждого свой стек, но сегменты x86 для этой цели не используются.

Возможно * nix делает что-то другое. Кто знает. Предпосылка, на которой был основан вопрос, была нарушена.


  1. Как минимум для пользовательского пространства.
  2. С ntsd notepad: cs=001b ss=0023 ds=0023 es=0023
19 голосов
/ 09 июля 2011

Обычно потоки называются легковесным процессом. Если мы разделим память на три части, то это будет: код, данные и стек. Каждый процесс имеет свой собственный раздел кода, данных и стека, и из-за этого время переключения контекста немного велико. Чтобы сократить время переключения контекста, люди придумали концепцию потока, который разделяет сегмент данных и кода с другим потоком / процессом и имеет собственный сегмент STACK.

16 голосов
/ 15 августа 2012

У процесса есть сегменты кода, данных, кучи и стека. Теперь указатель инструкций (IP) потока ИЛИ потока указывает на сегмент кода процесса. Сегменты данных и кучи совместно используются всеми потоками. А как насчет области стека? Что на самом деле площадь стека? Это область, созданная процессом только для использования его потока ... потому что стеки могут использоваться намного быстрее, чем кучи и т. Д. Область стека процесса делится между потоками, то есть, если есть 3 потока, то Область стека процесса делится на 3 части, и каждая отводится 3 потокам. Другими словами, когда мы говорим, что каждый поток имеет свой собственный стек, этот стек фактически является частью области стека процесса, выделенной каждому потоку. Когда поток завершает свое выполнение, стек потока освобождается процессом. Фактически, не только стек процесса разделен между потоками, но и весь набор регистров, который поток использует как SP, PC и регистры состояния, являются регистрами процесса. Поэтому, когда дело доходит до совместного использования, код, данные и области кучи являются общими, а область стека просто делится между потоками.

12 голосов
/ 19 ноября 2009

Потоки разделяют код, сегменты данных и кучу, но не разделяют стек.

5 голосов
/ 19 ноября 2009

Потоки обмениваются данными и кодом, а процессы - нет. Стек не является общим для обоих.

Процессы также могут совместно использовать память, точнее код, например, после Fork(), но это детали реализации и (операционная система) оптимизация. Код, совместно используемый несколькими процессами, будет (надеюсь) дублироваться при первой записи в код - это называется копирование при записи . Я не уверен в точной семантике для кода потоков, но я предполагаю, что общий код.

           Process   Thread

   Stack   private   private
   Data    private   shared
   Code    private<sup>1</sup>  shared<sup>2</sup>

1 Код логически закрытый, но может использоваться совместно для повышения производительности. 2 Я не уверен на 100%.

4 голосов
/ 19 ноября 2009

Темы делятся всем [1]. Для всего процесса существует одно адресное пространство.

Каждый поток имеет свой собственный стек и регистры, но стеки всех потоков видны в общем адресном пространстве.

Если один поток выделяет какой-либо объект в своем стеке и отправляет адрес другому потоку, они оба будут иметь равный доступ к этому объекту.


На самом деле, я только что заметил более широкую проблему: я думаю, что вы путаете два употребления слова сегмент .

Формат файла для исполняемого файла (например, ELF) содержит отдельные разделы, которые могут называться сегментами, содержащими скомпилированный код (текст), инициализированные данные, символы компоновщика, отладочную информацию и т. Д. Кучи нет. или стековые сегменты здесь, так как это конструкции только для выполнения.

Эти двоичные сегменты файлов могут отображаться в адресное пространство процесса отдельно с различными разрешениями (например, исполняемый файл только для чтения для кода / текста и неисполняемый файл копирования при записи для инициализированных данных).

Области этого адресного пространства используются для различных целей, таких как выделение кучи и стек потоков, по соглашению (обеспечивается вашими языковыми библиотеками времени выполнения). Это все только память, и, вероятно, не сегментированная, если вы не работаете в режиме виртуального 8086. Стек каждого потока представляет собой кусок памяти, выделенный во время создания потока, с текущим верхним адресом стека, хранящимся в регистре указателя стека, и каждый поток сохраняет свой собственный указатель стека вместе со своими другими регистрами.


[1] Хорошо, я знаю: маски сигналов, TSS / TSD и т. Д. Адресное пространство, включая все сегменты его сопоставленных программ, все еще используется совместно.

2 голосов
/ 21 июня 2011

В платформе x86 можно разделить столько сегментов (до 2 ^ 16-1). Директивы ASM SEGMENT / ENDS позволяют это, а операторы SEG и OFFSET позволяют инициализировать регистры сегментов. CS: IP обычно инициализируется загрузчиком, но для DS, ES, SS приложение отвечает за инициализацию. Во многих средах допускаются так называемые «упрощенные определения сегментов», такие как .code, .data, .bss, .stack и т. Д., И, в зависимости от «модели памяти» (маленькая, большая, компактная и т. Д.), Загрузчик инициализирует регистры сегментов. соответственно. Обычно .data, .bss, .stack и другие обычные сегменты (я не делал это с 20 лет, поэтому я не помню все) сгруппированы в одну группу, поэтому обычно DS, ES и SS указывают на та же область, но это только для упрощения вещей.

Как правило, все регистры сегментов могут иметь разные значения во время выполнения. Итак, вопрос интервью был правильным: какой из CODE, DATA и STACK разделен между потоками. Управление кучей - это нечто другое - это просто последовательность обращений к ОС. Но что, если у вас вообще нет ОС, как во встроенной системе - можете ли вы по-прежнему добавлять / удалять в своем коде?

Мой совет молодым людям - прочитайте хорошую книгу по программированию на ассемблере. Кажется, что университетские учебные планы в этом отношении довольно плохие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...