Какие темы делятся вообще?


20

Ну, это общий вопрос. И если кто-то захочет сделать это специфичным для реализации, тогда я предпочту Unix-связанные вещи. Но для начала нужно знать следующие проблемы в целом:

Я прочитал один процесс может иметь несколько потоков. Несколько потоков одного процесса делят вещи между ними. Я хочу знать, что они разделяют, а что нет. Рассматриваемый процесс состоит из адресного пространства, стека, кучи, глобальных переменных, кода, данных, ресурсов ОС, что среди них разделяется потоками? У меня есть следующие предположения:

  1. Глобальные переменные - я прочитал ветку общих переменных. Также во время программирования на Java и C # я создал потоки для совместного использования переменных уровня класса. Поэтому я считаю, что потоки имеют общие глобальные переменные (хотя и не уверены, что концепции в языках программирования высокого уровня переводятся как факты низкого уровня операционной системы).

  2. Куча - поскольку глобальная переменная хранится в куче, куча распределяется между потоками.

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

Теперь я не уверен в том, чтобы делиться следующими вещами

  1. Адресное пространство - не уверен, что именно считается под адресным пространством. Но я думаю, что адресное пространство обычно используется в контексте процессов, а не потоков. И поскольку все потоки одного и того же процесса находятся в том же адресном пространстве, что и родительский процесс, говорят, что потоки совместно используют адресное пространство. (Но тогда они поддерживают другой стек внутри одного и того же адресного пространства?)

  2. Ресурсы ОС - я думаю, это может зависеть от конкретной реализации. Например, родительский процесс может выборочно передавать дескриптор одного и того же файла некоторым его потокам, а не всем. Или я ошибаюсь, а ресурсы ОС означают что-то, кроме файлов?

  3. Код - потоки могут иметь другой код, поэтому совместное использование кода не всегда так.

  4. Данные - не уверены, что следует учитывать в данных. Но убедитесь, что глобальные переменные являются общими для всех потоков. И уверен, что локальные переменные не разделяются аналогичным образом.

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

Ответы:


13

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

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

Адресное пространство , это просто отображение логических адресов на конкретные куски физической памяти. Поэтому, когда мы говорим, что все потоки в процессе используют одно и то же адресное пространство, мы имеем в виду, что при обращении к переменной fooв глобальной области видимости все потоки будут видеть одну и ту же переменную. Точно так же все потоки могут запускать разные точки в коде в любое конкретное время, но им всем разрешено вызывать глобальную функцию bar(), которая будет соответствовать одной и той же функции для каждого потока в процессе.

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

* Существует некоторое дополнительное состояние процесса, общее для всех потоков процесса, таких как идентификатор процесса, обработка сигналов и блокировки файлов. Для получения полного списка состояний процесса, совместно используемых потоками, вам нужно обратиться к документации для конкретной реализации потоков. Например, справочная страница pthreads .


4

Потоки имеют две перспективы: операционные системы и языки программирования. В обоих случаях есть некоторые различия в атрибутах потока.

Минимальное определение потока - это то, что это происходит последовательно, одно за другим.

В типичной модели машинного исполнения каждый поток имеет свой собственный набор регистров общего назначения и свой собственный программный счетчик. Если машина устанавливает конкретный регистр в качестве указателя стека, существует одна копия на поток.

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

В многозадачной операционной системе, которая обеспечивает изоляцию между задачами (или процессами , вы можете рассматривать эти термины как синонимы в контексте ОС), каждая задача имеет свои собственные ресурсы, в частности адресное пространство, но также и открытые файлы, привилегии и т. Д. Изоляция имеет быть предоставленным ядром операционной системы , сущностью, которая находится над процессами. У каждой задачи обычно есть по крайней мере один поток - задача, которая не выполняет код, не очень полезна. Операционная система может поддерживать или не поддерживать несколько потоков в одной задаче; например, оригинальный Unix этого не сделал. Задача все еще может запускать несколько потоков, организуя переключение между ними - для этого не требуется никаких специальных привилегий. Это называется « пользовательские темы»», Особенно в контексте Unix. В настоящее время большинство систем Unix предоставляют потоки ядра, в частности потому, что это единственный способ иметь несколько потоков одного и того же процесса на разных процессорах.

Большинство ресурсов операционной системы, кроме времени вычислений, привязаны к задачам, а не потокам. Некоторые операционные системы (например, Linux) явно разграничивают стеки, и в этом случае каждый поток имеет свой собственный; но есть операционные системы, в которых ядро ​​ничего не знает о стеках, они всего лишь часть кучи, насколько это возможно. Ядро также обычно управляет контекстом ядра для каждого потока, который является структурой данных, содержащей информацию о том, что поток делает в настоящее время; это позволяет ядру обрабатывать несколько потоков, заблокированных в системном вызове одновременно.

Что касается операционной системы, то потоки задачи выполняют один и тот же код, но находятся в разных позициях в этом коде (разные значения счетчика программы). Может случиться или не случиться так, что определенные части кода программы всегда выполняются в определенных потоках, но обычно есть общий код (например, служебные функции), который может быть вызван из любого потока. Все потоки видят одни и те же данные, иначе они будут рассматриваться как разные задачи; если к некоторым данным может получить доступ только конкретный поток, это обычно относится исключительно к языку программирования, а не к операционной системе.

В большинстве языков программирования память распределяется между потоками одной и той же программы. Это модель параллельного программирования с общей памятью ; он очень популярен, но также подвержен ошибкам, потому что программист должен быть осторожен, когда одни и те же данные могут быть доступны нескольким потокам, поскольку могут возникнуть условия гонки . Обратите внимание, что даже локальные переменные могут совместно использоваться потоками: «локальная переменная» (обычно) означает переменную, имя которой допустимо только во время одного выполнения функции, но другой поток может получить указатель на эту переменную и получить к ней доступ.

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

Некоторые языки смешивают две модели, предлагая локальное хранилище потоков с системой типов или без нее, чтобы отличать локальное хранилище потоков от глобальных. Локальное хранилище потоков - это, как правило, удобная функция, которая позволяет имени переменной обозначать разные места хранения в разных потоках.

Некоторые (сложные) наблюдения, которые могут быть интересны, чтобы понять, что такое потоки:

  • Какой минимум требуется ядру для поддержки нескольких потоков?
  • В многопроцессорной среде, что нужно для переноса потока с одного процессора на другой?
  • Что потребуется для реализации совместной многопоточности ( сопрограммы ) на вашем любимом языке программирования без поддержки операционной системы и без использования встроенной поддержки, если таковая имеется? (Помните, что большинство языков программирования не имеют необходимых примитивов для реализации сопрограмм внутри одного потока.)
  • Как мог бы выглядеть язык программирования, если бы он имел параллелизм, но не имел (явного) понятия потоков? (Главный пример: пи-исчисление .)

Это самая интересная вещь, которую я читал за несколько месяцев.
JSON

2

Это зависит. Если вы рассматриваете потоки как определенные, например, POSIX (и предлагаемые системами Unix) или Windows (не знакомые с последним, вам нужно будет спросить конкретно), тогда это дает ваш ответ (по сути, как объясняет ответ @WanderingLogic). У Linux есть собственное представление о потоках, использующее нестандартный clone(2)системный вызов. Он предлагает довольно детальный контроль над тем, что разделяет родитель и ребенок. Он идет до того, что имеет внутреннюю оболочку fork(2)и, по vfork(2)сути, оборачивает ее clone(2), вызывая ее с определенными флагами, т. Е. Вы можете создавать «потоки», которые почти ничего не делят с родителем. Посмотрите его страницу руководства для деталей, они доступны онлайн, например, здесь . Да, Linux предлагает потоки в стиле POSIX, но, кроме того, гораздо больше.


0

Темы делятся:

  • Адресное пространство
  • отвал
  • Статические данные
  • Сегменты кода
  • Файловые дескрипторы
  • Глобальные переменные
  • Дочерние процессы
  • Ожидающие тревоги
  • Сигналы и обработчики сигналов
  • Бухгалтерская информация

Темы имеют свои:

  • Счетчик команд
  • Регистры
  • стек
  • состояние
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.