Які нитки поділяють загалом?


20

Ну це загальне питання. І якщо хтось хоче зробити його реалізацією специфічною, то я віддаю перевагу речей, що стосуються Unix. Але спершу потрібно знати в основному такі проблеми:

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

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

  2. Heap - Оскільки глобальна змінна зберігається в купі, купа поділяється між потоками.

  3. Стек - Оскільки кожен потік може мати власну послідовність / код виконання, він повинен мати власний стек, на який він може натискати / висувати вміст лічильника програми (коли функція скажіть викликає та повертається). Тож потоки одного процесу не ділять стек.

Зараз я не впевнений у спільному використанні наступних речей

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

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

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

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

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

Відповіді:


13

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

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

Адресний простір , це просто відображення логічних адрес на конкретні шматки фізичної пам'яті. Отже, коли ми кажемо, що всі потоки в процесі мають однаковий адресний простір, ми маємо на увазі, що при доступі до змінної fooв глобальному масштабі всі потоки побачать однакову змінну. Аналогічно, всі потоки можуть виконувати іншу точку коду в будь-який конкретний час, але всім їм дозволено викликати глобальну функцію bar(), яка відповідатиме однаковій функції для кожного потоку в процесі.

Більшість сучасних операційних систем додали поняття локального зберігання потоків , які є змінними глобального масштабу, які не поділяються. Звичайний приклад використання цього є для змінної errno. Це єдина змінна глобальної сфери, але в більшості сучасних операційних систем кожному потоку надається своя локальна копія, так що помилка виклику бібліотеки на одному потоці не вплине на поведінку інших потоків.

* Існує деякий додатковий стан процесу, яким поділяються всі потоки процесу, такі як ідентифікатор процесу, обробка сигналу та блокування файлів. Для повного переліку стану процесів, що ділиться потоками, вам потрібно переглянути документацію для конкретної реалізації потоків. Наприклад, сторінка man pthreads .


4

Нитки складаються з двох перспектив: операційні системи та мови програмування. В обох випадках існує певна зміна у тому, які атрибути має нитка.

Мінімальне визначення потоку полягає в тому, що це речі, які відбуваються послідовно, одна за іншою.

У типовій моделі виконання машин кожен потік має власний набір регістрів загального призначення та власний лічильник програм. Якщо машина задає певний регістр як вказівник стека, є одна копія на потік.

З точки зору операційної системи мінімум, який потрібно зробити операційній системі для підтримки потоків - це спосіб перемикатися між ними. Це може статися або автоматично ( попереджувальна багатозадачність, або лише тоді, коли потік робить явний запит (кооперативний багатозадачність; в такому випадку нитки іноді називають волокнами ). Також існують гібридні моделі як з попередньою, так і з кооперативною віддачею, наприклад, попередження між потоками різних груп або завдання, але явний вихід між потоками однієї групи / завдання. Перемикання між потоками передбачає мінімальне збереження регістрових значень старого потоку та відновлення значень регістра нового потоку.

У багатозадачній операційній системі, яка забезпечує ізоляцію між завданнями (або процесами , ви можете трактувати ці терміни як синоніми в контексті ОС), кожне завдання має власні ресурси, зокрема адресний простір, а також відкриті файли, привілеї тощо. Ізоляція має повинні бути надані ядром операційної системи , суттю, що вище процесів. У кожному завданні зазвичай є щонайменше один потік - завдання, яке не виконує код, не має великої користі. Операційна система може або не може підтримувати кілька потоків в одному і тому ж завданні; наприклад, оригінальний Unix цього не зробив. Завдання все ще може запускати кілька потоків, організовуючи перемикатися між ними - для цього не потрібні спеціальні привілеї. Це називається " потоки користувачів "", Особливо в контексті Unix. На сьогоднішній день більшість систем Unix надають потоки ядра, зокрема, тому що це єдиний спосіб мати кілька потоків одного і того ж процесу на різних процесорах.

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

Що стосується операційної системи, тони завдання виконують один і той же код, але знаходяться в різних положеннях у цьому коді (різні значення лічильника програми). Можливо, може статися, що певні частини коду програми завжди виконуються у певних потоках, але зазвичай існує загальний код (наприклад, функції утиліти), який можна викликати з будь-якого потоку. Усі потоки бачать однакові дані, інакше вони вважатимуться різними завданнями; якщо до деяких даних можна отримати доступ лише певним потоком, це, як правило, виключно сфера використання мови програмування, а не операційної системи.

У більшості мов програмування зберігання поділяється між потоками однієї програми. Це модель спільної пам'яті одночасного програмування; це дуже популярно, але також дуже схильне до помилок, тому що програмісту потрібно бути обережним, коли до одних і тих же даних можна отримати доступ через декілька потоків, оскільки можуть виникати умови перегонів . Зауважте, що навіть локальні змінні можуть бути розподілені між потоками: "локальна змінна" (зазвичай) означає змінну, ім'я якої дійсне лише під час одного виконання функції, але інший потік може отримати вказівник на цю змінну та отримати доступ до неї.

Існують також мови програмування, де кожен потік має власне сховище, а зв’язок між ними відбувається шляхом надсилання повідомлень по каналах зв'язку. Це модель передачі повідомлень одночасного програмування. Ерлангє основною мовою програмування, яка зосереджена на передачі повідомлень; середовище його виконання має дуже легку обробку потоків, і це заохочує програми, написані багатьма короткочасними потоками, на відміну від більшості інших мов програмування, де створення потоку є відносно дорогою операцією, а середовище виконання не може підтримувати дуже великі кількість ниток одночасно. Послідовна підмножина Ерланга (частина мови, яка відбувається всередині потоку, зокрема маніпулювання даними) є (здебільшого) чисто функціональною; таким чином, потік може відправити повідомлення в інший потік, що містить деякі дані, і жоден потік не повинен турбуватися про те, що дані змінюються іншим потоком під час його використання.

Деякі мови поєднують дві моделі, пропонуючи локальне зберігання потоків, із системою типу або без нього, щоб відрізняти місце локального зберігання від глобального. Місцеве зберігання ниток - це звичайна функція, яка дозволяє імені змінної призначити різні місця зберігання в різних потоках.

Деякі (складні) подальші дії, які можуть бути цікавими для розуміння, що таке теми:

  • Що таке мінімум, який повинен зробити ядро ​​для підтримки декількох потоків?
  • У багатопроцесорному середовищі що потрібно для переміщення потоку з одного процесора на інший?
  • Що потрібно для впровадження кооперативної багатопотокової роботи ( розробки ) на вашій улюбленій мові програмування без підтримки операційної системи та без використання її вбудованої підтримки, якщо така є? (Будьте уважні, що більшості мов програмування не вистачає необхідних примітивів, щоб реалізувати супроводи всередині однієї нитки.)
  • Як може виглядати мова програмування, якби вона мала паралельність, але не має (явного) поняття потоків? (Основний приклад: пі-числення .)

Це найцікавіше, що я читав за місяці.
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.