Реализация потоков в ядре кратко

Обновлено: 05.07.2024

Многопоточность — это популярная сегодня программная абстракция. Она обеспечивает выполнение нескольких потоков в совместно используемом адресном пространстве памяти. Потоки также могут совместно использовать открытые файлы и другие ресурсы. Многопоточность используется для параллельного программирования (concurrent programming), что на многопроцессорных системах обеспечивает истинный параллелизм.

Реализация потоков в операционной системе Linux уникальна. Для ядра Linux не существует отдельной концепции потоков. В ядре Linux потоки реализованы так же, как и обычные процессы. В ОС Linux нет никакой особенной семантики для планирования выполнения потоков или каких-либо особенных структур данных для представления потоков. Поток— это просто процесс, который использует некоторые ресурсы совместно с другими процессами. Каждый поток имеет структуру task_struct и представляется для ядра обычным процессом (который совместно использует ресурсы, такие как адресное пространство, с другими процессами).

В этом смысле Linux отличается от других операционных систем, таких как Microsoft Windows или Sun Solaris, которые имеют явные средства поддержки потоков в ядре (в этих системах иногда потоки называются процессами с быстрым переключением контекста, lightweight process). Название "процесс с быстрым переключением контекста" показывает разницу между философией Linux и других операционных систем. Для остальных операционных систем потоки— это абстракция, которая обеспечивает облегченные, более быстрые для исполнения сущности, чем обычные тяжелые процессы. Для операционной системы Linux потоки — это просто способ совместного использования ресурсов несколькими процессами (которые и так имеют достаточно малое время переключения контекста)[18].

Допустим, у нас есть процесс, состоящий из четырех потоков. В операционных системах с явной поддержкой потоков должен существовать дескриптор процесса, который далее указывает на четыре потока. Дескриптор процесса описывает совместно используемые ресурсы, такие как адресное пространство и открытые файлы. Потоки описываются ресурсами, которые принадлежат только им. В ОС Linux, наоборот, существует просто четыре процесса и, соответственно, четыре обычные структуры task_struct. Четыре процесса построены так, чтобы совместно использовать определенные ресурсы.

Потоки создаются так же, как и обычные задания, за исключением того, что в системный вызов clone() передаются флаги с указанием, какие ресурсы должны использоваться совместно:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

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

а вызов vfork() в таком виде:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0);

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

Таблица 3.1. Флаги системного вызова clone()

Флаг Описание CLONE_FILES Родительский и порожденный процессы совместно используют открытые файлы CLONE_FS Родительский и порожденный процессы совместно используют информацию о файловой системе CLONE_IDLETASK Установить значение PID в нуль (используется только для холостых (idle) задач) CLONE_NEWNS Создать новое пространство имен для порожденной задачи CLONE_PARENT Родительский процесс вызывающего процесса становится родительским и для порожденного CLONE_PTRACE Продолжить трассировку и для порожденного процесса CLONE_SETTID Возвратить значение идентификатора TID в пространство пользователя CLONE_SETTLS Для порожденного процесса создать новую область локальных данных потока (thread local storage, TLS) CLONE_SIGHAND У порожденного и родительского процессов будут общие обработчики сигналов CLONE_SYSVSEM У родительского и порожденного процессов будет общая семантика обработки флага SEM_UNDO для семафоров System V CLONE_THREAD Родительский и порожденный процессы будут принадлежать одной группе потоков CLONE_VFORK Использовать vfork(): родительский процесс будет находиться а приостановленном состоянии, пока порожденный процесс не возобновит его работу CLONE_UNTRACED Запретить родительскому процессу использование флага CLONE_PTRACE для порожденного процесса CLONE_STOP Запустить процесс в состоянии TASK_STOPPED CLONE_CHILD_CLEARTID Очистить идентификатор TID для порожденного процесса CLONE_CHILD_SETTID Установить идентификатор TID для порожденного процесса CLONE_PARENT_SETTID Установить идентификатор TID для родительского процесса CLONE_VM У порожденного и родительского процессов будет общее адресное пространство

Стеки потоков и допустимые количества потоков

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

Глава 2 Начальные сведения о ядре Linux

Глава 2 Начальные сведения о ядре Linux В этой главе будут рассмотрены основные вопросы, связанные с ядром Linux: где получить исходный код, как его компилировать и как инсталлировать новое ядро. После этого рассмотрим некоторые допущения, связанные с ядром Linux, отличия между

Глава 9 Средства синхронизации в ядре

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

Информация о времени в ядре

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

Порядок байтов в ядре

Порядок байтов в ядре Для каждой аппаратной платформы, которая поддерживается ядром Linux, в файле <asm/byteorder.h> определена одна из двух констант __BIG_ENDIAN или __LITTLE_ENDIAN, в соответствии с используемым порядком байтов.В этот заголовочный файл также включаются макросы из

Реализация связанных списков в ядре Linux

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

IPLabs Linux Team: начало русского Linux’а

IPLabs Linux Team: начало русского Linux’а Следующая веха на пути русского Linux’а – 1998 год, когда фирма IPLabs (точнее, ее подразделение – IPLabs Linux Team) совместно с Институтом логики (на самом деле это были одни и те же люди – Алексей Новодворский, Алексей Смирнов и Юрий Девяткин с

Утилита apt. Реализация для Linux Mint

Утилита apt. Реализация для Linux Mint В данном очерке рассмотрены особенности утилиты apt в реализации для дистрибутива Linux Mint и её отличия от семейства утилит, входящих в пакет apt, общий для всех deb based

О ядре баз данных

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

13.1.6. Группы потоков

13.1.6. Группы потоков Группа потоков — это механизм управления логически связанными потоками. По умолчанию все потоки принадлежат группе Default (это константа класса). Но если создать новую группу, то в нее можно будет помещать потоки.В любой момент времени поток может

Пул потоков CLR

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

4.5. Реализация потоков в Linux

4.5. Реализация потоков в Linux Потоковые функции, соответствующие стандарту POSIX, реализованы в Linux не так, как в большинстве других версий UNIX. Суть в том, что в Linux потоки реализованы в виде процессов. Когда вызывается функция pthread_create(), операционная система на самом деле

7.4. Информация о ядре

7.4. Информация о ядре В файловой системе /proc есть много элементов, содержащих информацию о настройках и состоянии ядра. Некоторые из них находятся на верхнем уровне файловой системы, а некоторые скрыты в каталоге

Закрытие потоков

Закрытие потоков Функции fclose и fcloseall закрывают поток или потоки. Функция fclose закрывает один заданный поток, fcloseall — все потоки, кроме потоков stdin, stdout, stderr, stdaux, stdprn.Если программа не выполняет закрытия потоков, потоки автоматически закрываются, когда программа завершается

Реализация NPTL для высших версий Linux

Реализация NPTL для высших версий Linux Новая библиотека потоков POSIX (Native POSIX Thread Library, NPTL) в Red Hat 9 (и, возможно, в более поздних дистрибутивах Linux) создает проблемы с Суперсервером и локально скомпилированными программами, а также с утилитами. Утилита gbak сообщает об ошибке "broken

vedro-compota

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

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

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

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

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

Основным недостатком управления потоками в ядре является существенная цена системных запросов

, поэтому постоянные ошибки с потоками (создание, завершение и т.п.) приведут к увеличению накладных расходов.

Потоки, процессы, контексты.

Системный вызов (syscall). Данное понятие, вы будете встречать достаточно часто в данной статье, однако несмотря на всю мощь звучания, его определение достаточно простое :) Системный вызов — это процесс вызова функции ядра, из приложение пользователя. Режим ядра — код, который выполняется в нулевом кольце защиты процессора (ring0) с максимальными привилегиями. Режим пользователя — код, исполняемый в третьем кольце защиты процессора (ring3), обладает пониженными привилегиями. Если код в ring3 будет использовать одну из запрещенных инструкций (к примеру rdmsr/wrmsr, in/out, попытку чтения регистра cr3, cr4 и т.д.), сработает аппаратное исключение и пользовательский процесс, чей код исполнял процессор в большинстве случаях будет прерван. Системный вызов осуществляет переход из режима ядра в режим пользователя с помощью вызова инструкции syscall/sysenter, int2eh в Win2k, int80h в Linux и т.д.

И так, что же такое поток? Поток (thread) — это, сущность операционной системы, процесс выполнения на процессоре набора инструкций, точнее говоря программного кода. Общее назначение потоков — параллельное выполнение на процессоре двух или более различных задач. Как можно догадаться, потоки были первым шагом на пути к многозадачным ОС. Планировщик ОС, руководствуясь приоритетом потока, распределяет кванты времени между разными потоками и ставит потоки на выполнение.

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

  • Регистры процессора.
  • Указатель на стек потока/процесса.
  • Если ваша задача требует интенсивного распараллеливания, используйте потоки одного процесса, вместо нескольких процессов. Все потому, что переключение контекста процесса происходит гораздо медленнее, чем контекста потока.
  • При использовании потока, старайтесь не злоупотреблять средствами синхронизации, которые требуют системных вызовов ядра (например мьютексы). Переключение в редим ядра — дорогостоящая операция!
  • Если вы пишете код, исполняемый в ring0 (к примеру драйвер), старайтесь обойтись без использования дополнительных потоков, так как смена контекста потока — дорогостоящая операция.

Классификация потоков

  • По отображению в ядро: 1:1, N:M, N:1
  • По многозадачной модели: вытесняющая многозадачность (preemptive multitasking), кооперативная многозадачность (cooperative multitasking).
  • По уровню реализации: режим ядра, режим польователя, гибридная реализация.

Классификация потоков по отображению в режим ядра

  • Центральный планировщик ОС режима ядра, который распределяет время между любым потоком в системе.
  • Планировщик библиотеки потоков. У библиотеки потоков режима пользователя может быть свой планировщик, который распределяет время между потоками различных процессов режима пользователя.
  • Планировщик потоков процесса. Уже рассмотренные нами волокна, ставятся на выполнение именно таким способом. К примеру свой Thread Manager есть у каждого процесса Mac OS X, написанного с использованием библиотеки Carbon.

Модель N:M отображает некоторое число потоков пользовательских процессов N на M потоков режима ядра. Проще говоря имеем некую гибридную систему, когда часть потоков ставится на выполнение в планировщике ОС, а большая их часть в планировщике потоков процесса или библиотеки потоков. Как пример можно привести GNU Portable Threads. Данная модель достаточно трудно реализуема, но обладает большей производительностью, так как можно избежать значительного количества системных вызовов.

Модель N:1. Как вы наверное догадались — множество потоков пользовательского процесса отображаются на один поток ядра ОС. Например волокна.

Классификация потоков по многозадачной модели

Во времена DOS, когда однозадачные ОС перестали удовлетворять потребителя, программисты и архитекторы задумали реализовать многозадачную ОС. Самое простое решение было следующим: взять общее количество потоков, определить какой-нибудь минимальный интервал выполнения одного потока, да взять и разделить между всеми -братьями- потоками время выполнения поровну. Так и появилось понятие кооперативной многозадачности (cooperative multitasking), т.е. все потоки выполняются поочередно, с равным временем выполнения. Никакой другой поток, не может вытеснить текущий выполняющийся поток. Такой очень простой и очевидный подход нашел свое применение во всех версиях Mac OS вплоть до Mac OS X, также в Windows до Windows 95, и Windows NT. До сих пор кооперативная многозадачность используется в Win32 для запуска 16 битных приложений. Также для обеспечения совместимости, cooperative multitasking используется менеджером потоков в Carbon приложениях для Mac OS X.

Однако, кооперативная многозадачность со временем показала свою несостоятельность. Росли объемы данных хранимых на винчестерах, росла также скорость передачи данных в сетях. Стало понятно, что некоторые потоки должны иметь больший приоритет, как-то потоки обслуживания прерываний устройств, обработки синхронных IO операций и т.д. В это время каждый поток и процесс в системе обзавелся таким свойством, как приоритет. Подробнее о приоритетах потоков и процессов в Win32 API вы можете прочесть в книге Джефри Рихтера, мы на этом останавливатся не будем ;) Таким образом поток с большим приоритетом, может вытеснить поток с меньшим. Такой прицип лег в основу вытесняющей многозадачности (preemptive multitasking). Сейчас все современные ОС используют данный подход, за исключением реализации волокон в пользовательском режиме.

Классификация потоков по уровню реализации

  1. Реализация потоков на уровне ядра. Проще говоря, это классическая 1:1 модель. Под эту категорию подпадают:
    • Потоки Win32.
    • Реализация Posix Threads в Linux — Native Posix Threads Library (NPTL). Дело в том, что до версии ядра 2.6 pthreads в Linux был целиком и полностью реализован в режиме пользователя (LinuxThreads). LinuxThreads реализовывалf модель 1:1 следующим образом: при создании нового потока, библиотека осуществляла системный вызов clone, и создавало новый процесс, который тем не менее разделял единое адресное пространство с родительским. Это породило множество проблем, к примеру потоки имели разные идентификаторы процесса, что противоречило некоторым аспектам стандарта Posix, которые касаются планировщика, сигналов, примитивов синхронизации. Также модель вытеснения потоков, работала во многих случаях с ошибками, по этому поддержку pthread решено было положить на плечи ядра. Сразу две разработки велись в данном направлении компаниями IBM и Red Hat. Однако, реализация IBM не снискала должной популярности, и не была включена ни в один из дистрибутивов, потому IBM приостановила дальнейшую разработку и поддержку библиотеки (NGPT). Позднее NPTL вошли в библиотеку glibc.
    • Легковесные ядерны потоки (Leight Weight Kernel Threads — LWKT), например в DragonFlyBSD. Отличие этих потоков, от других потоков режима ядра в том, что легковесные ядерные потоки могут вытеснять другие ядерные потоки. В DragonFlyBSD существует множество ядерных потоков, например поток обслуживания аппаратных прерываний, поток обслуживания программных прерываний и т.д. Все они работают с фиксированным приоритетом, так вот LWKT могут вытеснять эти потоки (preempt). Конечно это уже более специфические вещи, про которые можно говорить бесконечно, но приведу еще два примера. В Windows все потоки ядра выполняются либо в контексте потока инициировавшего системный вызов/IO операцию, либо в контексте потока системного процесса system. В Mac OS X существует еще более интересная система. В ядре есть лишь понятие task, т.е. задачи. Все операции ядра выполняются в контексте kernel_task. Обработка аппаратного прерывания, к примеру, происходит в контексте потока драйвера, который обслуживает данное прерывание.
  2. Реализация потоков в пользовательском режиме. Так как, системный вызов и смена контекста — достаточно тяжелые операции, идея реализовать поддержку потоков в режиме пользователя витает в воздухе давно. Множество попыток было сделано, однако данная методика популярности не обрела:
    • GNU Portable Threads — реализация Posix Threads в пользовательском режиме. Основное преимущество — высокая портабельность данной библиотеки, проще говоря она может быть легко перенесена на другие ОС. Проблему вытиснения потоков в данной библиотеке решили очень просто — потоки в ней не вытесняются :) Ну и конечно ни о какой мультмпроцессорности речь идти не может. Данная библиотека реализует модель N:1.
    • Carbon Threads, которые я упоминал уже не раз, и RealBasic Threads.
  3. Гибридная реализация. Попытка использовать все преимущества первого и второго подхода, но как правило подобные мутанты обладают гораздо бОльшими недостатками, нежели достоинствами. Один из примеров: реализация Posix Threads в NetBSD по модели N:M, которая была посже заменена на систему 1:1. Более подробно вы можете прочесть в публикации Scheduler Activations: Effective Kernel Support for the User-Level Management of Parallelism.

Win32 API Threads

Если вы все еще не устали, предлагаю небольшой обзор API для работы с потоками и средствами синхронизации в win32 API. Если вы уже знакомы с материалом, можете смело пропускать этот раздел ;)

Средства синхронихации в Win32 есть двух типов: реализованные на уровне пользователя, и на уровне ядра. Первые — это критические секции (critical section), к второму набору относят мьютексы (mutex), события (event) и семафоры (semaphore).

Критические секции — легковесный механизм синхронизации, который работает на уровне пользовательского процесса и не использует тяжелых системных вызовов. Он основан на механизме взаимных блокировок или спин локов (spin lock). Поток, который желает обезопасить определенные данные от race conditions вызывает функцию EnterCliticalSection/TryEnterCriticalSection. Если критическая секция свободна — поток занимает ее, если же нет — поток блокируется (т.е. не выполняется и не отъедает процессорное время) до тех пор, пока секция не будет освобождена другим потоком с помощью вызова функции LeaveCriticalSection. Данные функции — атомарные, т.е. вы можете не переживать за целостность ваших данных ;)

  • Они использует примитивы ядра при выполнении, т.е. системные вызовы, что сказывается не производительности.
  • Могут быть именованными и не именованными, т.е. каждому такому объекту синхронизации можно присвоить имя.
  • Работают на уровне системы, а не на уровне процесса, т.е. могут служить механизмом межпроцессного взаимодействия (IPC).
  • Используют для ожидания и захвата примитива единую функцию: WaitForSingleObject/WaitForMultipleObjects.

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.

Прощальное слово

На сегодня пожалуй все, иначе информации станет слишком много. Для интересующихся, есть несколько полезных ссылок и книг внизу ;) Также высказывайте свое мнение, интересны ли вам статьи по данной теме.

UPD: дополнил статью небольшой информацией о режиме ядра и режиме пользователя.
UPD2: исправил досадные промахи и ошибки. Спасибо комментаторам ;)


· управление потоками возлагается на программу пользователя.

· системный вызов блокирует не только работающий поток, но и все потоки того процесса, к которому он относится;

· приложение не может работать в многопроцессорном режиме, так как ядро закрепляет за каждым процессом только один процессор;

· при запуске одного потока ни один другой поток а рамках одного процесса не будет запущен пока первый добровольно не отдаст процессор;


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

· возможно планирование работы нескольких потоков одного и того же процесса на нескольких процессорах;

· реализуется мультипрограммирование в рамках всех процессов (в том числе одного);

· при блокировании одного из потоков процесса ядро может выбрать другой поток этого же (или другого процесса);

· процедуры ядра могут быть многопоточными.

Необходимость двукратного переключения режима пользователь – ядро, ядро – пользователь для передачи управления от одного потока к другому в рамках одного и того же процесса.

Способы реализации пакета потоков:

· в пространстве пользователя (user - level threads – ULT);

· в ядре (kernel – level threads – KLT).


· можно реализовать в ОС, не поддерживающей потоки без каких-либо изменений в ОС;

· высокая производительность, поскольку процессу не нужно переключаться в режим ядра и обратно;

· ядро о потоках ничего не знает и управляет однопоточными процессами;

· имеется возможность использования любых алгоритмов планирования потоков с учетом их специфики;

· управление потоками возлагается на программу пользователя.

· системный вызов блокирует не только работающий поток, но и все потоки того процесса, к которому он относится;

· приложение не может работать в многопроцессорном режиме, так как ядро закрепляет за каждым процессом только один процессор;

· при запуске одного потока ни один другой поток а рамках одного процесса не будет запущен пока первый добровольно не отдаст процессор;


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

· возможно планирование работы нескольких потоков одного и того же процесса на нескольких процессорах;

· реализуется мультипрограммирование в рамках всех процессов (в том числе одного);

· при блокировании одного из потоков процесса ядро может выбрать другой поток этого же (или другого процесса);

· процедуры ядра могут быть многопоточными.

Необходимость двукратного переключения режима пользователь – ядро, ядро – пользователь для передачи управления от одного потока к другому в рамках одного и того же процесса.

Читайте также: