Недавно в интервью мне задали вопрос, в чем разница между процессом и потоком. Действительно, я не знал ответа. Я немного подумал и дал очень странный ответ.
Потоки разделяют одну и ту же память, процессы - нет. После ответа на это интервьюер злобно улыбнулся мне и задал мне следующие вопросы:
В. Знаете ли вы сегменты, в которых программа делится?
Мой ответ: да (думал, что это было легко) Стек, Данные, Код, Куча
Q. Итак, скажите мне: какими сегментами делятся потоки?
Я не мог ответить на это и в итоге сказал все из них.
Пожалуйста, кто-нибудь может представить правильные и впечатляющие ответы на разницу между процессом и потоком?
Ответы:
Вы в значительной степени правы, но потоки разделяют все сегменты, кроме стека. Потоки имеют независимые стеки вызовов, однако память в других стеках потоков по-прежнему доступна, и теоретически вы можете держать указатель на память в кадре локального стека другого потока (хотя вам, вероятно, следует найти лучшее место для размещения этой памяти!).
источник
Из Википедии (я думаю, это было бы действительно хорошим ответом для интервьюера: P)
источник
Что-то, на что действительно нужно обратить внимание, состоит в том, что в этом вопросе действительно есть два аспекта - теоретический аспект и аспект реализации.
Сначала давайте посмотрим на теоретический аспект. Вам необходимо понять, что такое концептуальный процесс, чтобы понять разницу между процессом и потоком и тем, что между ними.
У нас есть следующее из раздела 2.2.2 Модель классической нити в современных операционных системах 3e от Tanenbaum:
Он продолжает:
Далее он предоставляет следующую таблицу:
Это то, что вам нужно для работы потоков. Как уже отмечали другие, такие вещи, как сегменты, являются деталями реализации, зависящими от ОС.
источник
Скажите интервьюеру, что это полностью зависит от реализации ОС.
Возьмите Windows x86 для примера. Есть только 2 сегмента [1], Код и Данные. И они оба сопоставлены с целым 2 ГБ (линейным, пользовательским) адресным пространством. База = 0, предел = 2 ГБ. Они бы сделали один, но x86 не позволяет сегменту быть как для чтения / записи, так и для выполнения. Таким образом, они сделали два и установили CS для указания на дескриптор кода, а остальные (DS, ES, SS и т. Д.) Для указания на другой [2]. Но оба указывают на то же самое!
Человек, опрашивающий вас, сделал скрытое предположение, что он или она не заявили, и это глупая уловка, которую нужно вытащить.
Так что относительно
Сегменты не имеют отношения к вопросу, по крайней мере, на Windows. Потоки разделяют все адресное пространство. Существует только 1 сегмент стека, SS, и он указывает на те же вещи, что и DS, ES и CS [2]. Т.е. все кровавое пространство пользователя . 0-2GB. Конечно, это не означает, что потоки имеют только 1 стек. Естественно, у каждого свой стек, но сегменты x86 для этой цели не используются.
Возможно * nix делает что-то другое. Кто знает. Предпосылка, на которой был основан вопрос, была нарушена.
ntsd notepad
:cs=001b ss=0023 ds=0023 es=0023
источник
Обычно потоки называются легковесным процессом. Если мы разделим память на три части, то это будет: код, данные и стек. Каждый процесс имеет свой собственный раздел кода, данных и стека, и из-за этого время переключения контекста немного велико. Чтобы сократить время переключения контекста, люди придумали концепцию потока, который разделяет сегмент данных и кода с другим потоком / процессом и имеет собственный сегмент STACK.
источник
Процесс имеет код, данные, кучу и сегменты стека. Теперь указатель инструкций (IP) потока ИЛИ потока указывает на сегмент кода процесса. Сегменты данных и кучи совместно используются всеми потоками. А как насчет области стека? Что на самом деле площадь стека? Это область, созданная процессом только для использования его потока ... потому что стеки могут использоваться намного быстрее, чем кучи и т. Д. Область стека процесса делится между потоками, то есть, если есть 3 потока, то Область стека процесса делится на 3 части, и каждая отводится 3 потокам. Другими словами, когда мы говорим, что каждый поток имеет свой собственный стек, этот стек фактически является частью области стека процесса, выделенной каждому потоку. Когда поток завершает свое выполнение, стек потока освобождается процессом. По факту, не только стек процесса разделен между потоками, но и все наборы регистров, которые использует поток, такие как SP, ПК и регистры состояния, являются регистрами процесса. Таким образом, когда дело доходит до совместного использования, код, данные и области кучи являются общими, а область стека просто делится между потоками.
источник
Потоки разделяют код и сегменты данных и кучу, но они не разделяют стек.
источник
Потоки обмениваются данными и кодом, а процессы - нет. Стек не является общим для обоих.
Процессы также могут совместно использовать память, точнее код, например после a
Fork()
, но это детали реализации и (операционная система) оптимизация. Код, совместно используемый несколькими процессами, будет (надеюсь) дублироваться при первой записи в код - это называется копированием при записи . Я не уверен в точной семантике для кода потоков, но я предполагаю, что общий код.1 Код является логически закрытым, но может использоваться совместно для повышения производительности. 2 Я не уверен на 100%.
источник
Темы делятся всем [1]. Есть одно адресное пространство для всего процесса.
Каждый поток имеет свой собственный стек и регистры, но стеки всех потоков видны в общем адресном пространстве.
Если один поток выделяет некоторый объект в своем стеке и отправляет адрес другому потоку, они оба будут иметь равный доступ к этому объекту.
На самом деле, я только что заметил более широкую проблему: я думаю, что вы путаете два использования слова « сегмент» .
Формат файла для исполняемого файла (например, ELF) содержит отдельные разделы, которые могут называться сегментами, содержащими скомпилированный код (текст), инициализированные данные, символы компоновщика, отладочную информацию и т. Д. Сегменты кучи или стека отсутствуют. здесь, так как это только конструкции времени выполнения.
Эти двоичные сегменты файла могут отображаться в адресное пространство процесса отдельно с различными разрешениями (например, исполняемый файл только для чтения для кода / текста и неисполняемый файл для копирования при записи для инициализированных данных).
Области этого адресного пространства используются для различных целей, таких как выделение кучи и стек потоков, согласно соглашению (обеспечивается вашими языковыми библиотеками времени выполнения). Это все только память, и, вероятно, не сегментированная, если вы не работаете в режиме виртуального 8086. Стек каждого потока представляет собой кусок памяти, выделенный во время создания потока, с текущим верхним адресом стека, хранящимся в регистре указателя стека, и каждый поток сохраняет свой собственный указатель стека вместе со своими другими регистрами.
[1] Хорошо, я знаю: маски сигналов, TSS / TSD и т. Д. Адресное пространство, включая все отображаемые сегменты программы, все еще используется совместно.
источник
В платформе 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 распределяется между потоками. Управление кучей - это нечто другое - это просто последовательность обращений к ОС. Но что, если у вас вообще нет операционной системы, как во встроенной системе - можете ли вы добавить / удалить в своем коде?
Мой совет молодым людям - прочитайте хорошую книгу по программированию на ассемблере. Кажется, что университетские учебные планы в этом отношении довольно плохие.
источник
Отрывок из: Интерфейс программирования Linux: Справочник по системному программированию Linux и UNIX, Майкл Керриск , стр. 619
источник
Поток разделяет кучу (есть исследование о куче, специфичной для потока), но текущая реализация разделяет кучу. (и конечно же код)
источник
В процессе все потоки совместно используют системный ресурс, такой как куча памяти и т. Д., А поток имеет свой собственный стек
Таким образом, ваши ответы должны быть кучей памяти, которую все потоки разделяют для процесса.
источник