Процессы и потоки
Download 91,12 Kb.
|
потоки
- Bu sahifa navigatsiya:
- Заключения
ПримерКаждый поток, как и каждый процесс, имеет свой контекст. Контекст — это структура, в которой сохраняются следующие элементы:
Также следует отметить, что в случае выполнения системного вызова потоком и перехода из режима пользователя, в режим ядра, происходит смена стека потока на стек ядра. При переключении выполнения потока одного процесса, на поток другого, ОС обновляет некоторые регистры процессора, которые ответственны за механизмы виртуальной памяти (например CR3), так как разные процессы имеют разное виртуальное адресное пространство. Здесь я специально не затрагиваю аспекты относительно режима ядра, так как подобные вещи специфичны для отдельно взятой ОС. В общем случае, справедливы следующие рекомендации:
Волокно (fiber) — облегченный поток, выполняемый в режиме пользователя. Волокно затребует значительно меньше ресурсов, и позволяет в некоторых случаях минимизировать количество системных вызовов и следственно увеличить производительность. Обычно волокна выполняются в контексте потока, который их создал и затребуют лишь сохранения регистров процессора при их переключении. Как-то небыли, но волокна не сыскали должной популярности. Они были реализованы в свое время в множестве BSD ОС, но со временем выбрасывались оттуда. Win32 API также реализует механизм волокон, но используется он лишь для облегчения парирования софта, написанного под другую ОС. Следует отметить, что за переключение волокон ответственен либо планировщик уровня процесса, либо переключение должно быть реализовано в самом приложении, проще говоря вручную С каждым процессом связывается его адресное пространство, из которого он может читать и в которое он может писать данные. Адресное пространство содержит:
Во многих операционных системах вся информация о каждом процессе, дополнительная к содержимому его собственного адресного пространства, хранится в таблице процессов операционной системы. Некоторые поля таблицы:
Модель процесса В многозадачной системе реальный процессор переключается с процесса на процесс, но для упрощения модели рассматривается набор процессов, идущих параллельно (псевдопараллельно). Рассмотрим схему с четырьмя работающими программами. В каждый момент времени активен только один процесс С права представлены параллельно работающие процессы, каждый со своим счетчиком команд. Разумеется, на самом деле существует только один физический счетчик команд, в который загружается логический счетчик команд текущего процесса. Когда время, отведенное текущему процессу, заканчивается, физический счетчик команд сохраняется в памяти, в логическом счетчике команд процесса. Создание процесса Три основных события, приводящие к созданию процессов (вызов fork или CreateProcess):
Во всех случаях, активный текущий процесс посылает системный вызов на создание нового процесса. В UNIX каждому процессу присваивается идентификатор процесса ( PID - Process IDentifier) Завершение процесса Четыре события, приводящие к остановке процесса (вызов exit или ExitProcess):
Таким образом, приостановленный процесс состоит из собственного адресного пространства, обычно называемого образом памяти (core image), и компонентов таблицы процессов (в числе компонентов и его регистры). Иерархия процессов В UNIX системах заложена жесткая иерархия процессов. Каждый новый процесс созданный системным вызовом fork, является дочерним к предыдущему процессу. Дочернему процессу достаются от родительского переменные, регистры и т.п. После вызова fork, как только родительские данные скопированы, последующие изменения в одном из процессов не влияют на другой, но процессы помнят о том, кто является родительским. В таком случае в UNIX существует и прародитель всех процессов - процесс init. Дерево процессов для систем UNIX Состояние процессов Три состояния процесса:
Возможные переходы между состояниями. 1. Процесс блокируется, ожидая входных данных 2. Планировщик выбирает другой процесс 3. Планировщик выбирает этот процесс 4. Поступили входные данные Переходы 2 и 3 вызываются планировщиком процессов операционной системы, так что сами процессы даже не знают о этих переходах. С точки зрения самих процессов есть два состояния выполнения и ожидания. На серверах для ускорения ответа на запрос клиента, часто загружают несколько процессов в режим ожидания, и как только сервер получит запрос, процесс переходит из "ожидания" в "выполнение". Этот переход выполняется намного быстрее, чем запуск нового процесса. 2 Потоки (нити, облегченный процесс) Понятие потока Каждому процессу соответствует адресное пространство и одиночный поток исполняемых команд. В многопользовательских системах, при каждом обращении к одному и тому же сервису, приходится создавать новый процесс для обслуживания клиента. Это менее выгодно, чем создать квазипараллельный поток внутри этого процесса с одним адресным пространством. Сравнение многопоточной системы с однопоточной Модель потока С каждым потоком связывается:
Потоки делят между собой элементы своего процесса:
В остальном модель идентична модели процессов. В POSIX и Windows есть поддержка потоков на уровне ядра. Преимущества использования потоков
Реализация потоков в пространстве пользователя, ядра и смешанное А - потоки в пространстве пользователя B - потоки в пространстве ядра В случае А ядро о потоках ничего не знает. Каждому процессу необходима таблица потоков, аналогичная таблице процессов. Преимущества случая А:
Недостатки случая А:
Классификация потоков Поскольку классификация потоков — вопрос неоднозначный, то предлагаю их классифицировать следующим способом:
Классификация потоков по отображению в режим ядра Как я уже упомянул, потоки могут быть созданы не только в режиме ядра, но и в режиме пользователя. Планировщиков потоков в ОС может быть несколько:
Модель 1:1 — самая простая модель. Согласно ее принципам, любой поток созданный в любом процессе управляется напрямую планировщиком ядра ОС. Т.е. имеем отображении 1 к 1 потока пользовательского процесса на поток ядра. Такая модель реализована в Linux начиная с ядра 2.6, а также Windows. Модель N:M отображает некоторое число потоков пользовательских процессов N на M потоков режима ядра. Проще говоря имеем некую гибридную систему, когда часть потоков ставится на выполнение в планировщике ОС, а большая их часть в планировщике потоков процесса или библиотеки потоков. Как пример можно привести GNU Portable Threads. Данная модель достаточно трудно реализуема, но обладает большей производительностью, так как можно избежать значительного количества системных вызовов. Модель N:1. Как вы наверное догадались — множество потоков пользовательского процесса отображаются на один поток ядра ОС. Например волокна.
Однако, кооперативная многозадачность со временем показала свою несостоятельность. Росли объемы данных хранимых на винчестерах, росла также скорость передачи данных в сетях. Стало понятно, что некоторые потоки должны иметь больший приоритет, как-то потоки обслуживания прерываний устройств, обработки синхронных IO операций и т.д. В это время каждый поток и процесс в системе обзавелся таким свойством, как приоритет. Подробнее о приоритетах потоков и процессов в Win32 API вы можете прочесть в книге Джефри Рихтера, мы на этом останавливатся не будем ;) Таким образом поток с большим приоритетом, может вытеснить поток с меньшим. Такой прицип лег в основу вытесняющей многозадачности (preemptive multitasking). Сейчас все современные ОС используют данный подход, за исключением реализации волокон в пользовательском режиме. Классификация потоков по уровню реализации Как мы уже успели обсудить, реализация планировщика потоков может осуществлятся на разных уровнях. Итак:
Win32 API Threads Если вы все еще не устали, предлагаю небольшой обзор API для работы с потоками и средствами синхронизации в win32 API. Если вы уже знакомы с материалом, можете смело пропускать этот раздел ;) Потоки в Win32 создаются с помощью функции CreateThread, куда передается указатель на функцию (назовем ее функцией потока), которая будет выполнятся в созданом потоке. Поток считается завершенным, когда выполнится функция потока. Если же вы хотите гарантировать, что поток завершен, то можно воспользоватся функцией TerminateThread, однако не злоупотребляйте ею! Данная функция «убивает» поток, и отнюдь не всегда делает это корректно. Функция ExitThread будет вызвана неявно, когда завершится функция потока, или же вы можете вызвать данную функцию самостоятельно. Главная ее задача — освободить стек потока и его хендл, т.е. структуры ядра, которые обслуживают данный поток. Поток в Win32 может пребывать в состоянии сна (suspend). Можно «усыпить поток» с помощью вызова функции SuspendThread, и «разбудить» его с помощью вызова ResumeThread, также поток можно перевести в состояние сна при создании, установив значение параметра СreateSuspended функции CreateThread. Не стоит удивлятся, если вы не увидите подобной функциональности в кроссплатформенных библиотеках, типа boost::threads и QT. Все очень просто, pthreads просто не поддерживают подобную функциональность. Средства синхронихации в Win32 есть двух типов: реализованные на уровне пользователя, и на уровне ядра. Первые — это критические секции (critical section), к второму набору относят мьютексы (mutex), события (event) и семафоры (semaphore). Критические секции — легковесный механизм синхронизации, который работает на уровне пользовательского процесса и не использует тяжелых системных вызовов. Он основан на механизме взаимных блокировок или спин локов (spin lock). Поток, который желает обезопасить определенные данные от race conditions вызывает функцию EnterCliticalSection/TryEnterCriticalSection. Если критическая секция свободна — поток занимает ее, если же нет — поток блокируется (т.е. не выполняется и не отъедает процессорное время) до тех пор, пока секция не будет освобождена другим потоком с помощью вызова функции LeaveCriticalSection. Данные функции — атомарные, т.е. вы можете не переживать за целостность ваших данных ;) О мьютексах, событиях и семафорах было сказано достаточно много, по этому детально останавливатся я на них не буду. Следует заметить, что у всех этих механизмов есть общие черты:
Posix Threads или pthreads Сложно представить, какая из *nix подобных операционных систем, не реализует этот стандарт. Стоит отметить, что pthreads также используется в различных операционных системах реального времени (RTOS), потому требование к этой библиотеке (вернее стандарту) — жестче. К примеру, поток pthread не может пребывать в состоянии сна. Также в pthread нет событий, но есть гораздо более мощный механизм — условных переменных (conditional variables), который с лихвой покрывает все необходимые нужды. Поговорим об отличиях. К примеру, поток в pthreads может быть отменен (cancel), т.е. просто снят с выполнения посредством системного вызова pthread_cancel в момент ожидания освобождения какого-нибудь мьютекса или условной переменной, в момент выполнения вызова pthread_join (вызывающий поток блокируется до тех пор, пока не закончит свое выполнение поток, приминительно к которому была вызвана функция) и т.д. Для работы с мьютексами и семафорами существует отдельные вызовы, как-то pthread_mutex_lock/pthread_mutex_unlock и т.д. Conditional variables (cv) обычно используется в паре с мьютексами в более сложных случаях. Если мьютекс просто блокирует поток, до тех пор, пока другой поток не освободит его, то cv создают условия, когда поток может заблокировать сам себя до тех пор, пока не произойдет какое-либо условия разблокировки. Например, механизм cv помогает эмулировать события в среде pthreads. Итак, системный вызов pthread_cond_wait ждет, пока поток не будет уведомлен о том, что случилось определенное событие. pthread_cond_signal уведомляет один поток из очереди, что cv сработала. pthread_cond_broadcast уведомляет все потоки, которые вызывали pthread_cond_wait, что сработала cv. ЗаключенияПроцессы и потоки являются важными концепциями в компьютерных системах. Процессы представляют собой исполняющиеся программы, которые могут быть разделены на несколько потоков для более эффективной работы. Потоки позволяют одновременно выполнять несколько задач в рамках одного процесса. Процессы и потоки являются основой многозадачности в операционных системах, позволяя эффективно использовать ресурсы компьютера и обеспечивая быстродействие приложений. Однако, необходимо учитывать, что слишком много процессов и потоков может привести к перегрузке системы и снижению ее производительности. Кроме того, необходимо учитывать безопасность при работе с процессами и потоками, чтобы избежать утечек данных или других проблем. В целом, процессы и потоки являются важными инструментами для создания эффективных и быстродействующих приложений в компьютерных системах. Однако, их использование должно быть осознанным и ограниченным, чтобы избежать проблем с производительностью и безопасностью. Download 91,12 Kb. Do'stlaringiz bilan baham: |
ma'muriyatiga murojaat qiling