Подтвердить что ты не робот

Связь между ядром и пользовательским потоком

Есть ли связь между ядром и пользовательским потоком?

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

http://www.informit.com/articles/printerfriendly.aspx?p=25075

Реализация потоков в пространстве пользователя

Существует два основных способа реализации пакета потоков: в пространстве пользователя и в ядре. Выбор умеренно спорный, и возможна гибридная реализация. Теперь мы опишем эти методы, а также их преимущества и недостатки.

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

Все эти реализации имеют одинаковую общую структуру, которая проиллюстрирована на рис. 2-8 (а). Потоки выполняются поверх системы времени выполнения, которая представляет собой набор процедур, которые управляют потоками. Мы уже видели четыре из них: thread_create, thread_exit, thread_wait и thread_yield, но обычно их больше.

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

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

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

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

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

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

Другая альтернатива возможна в том случае, если можно заранее сообщить, будет ли вызов блокироваться. В некоторых версиях UNIX существует системный вызов, select, exists, который позволяет вызывающему абоненту определить, будет ли предполагаемое чтение блокироваться. Когда этот вызов присутствует, чтение процедуры библиотеки можно заменить на новую, которая сначала выполняет вызов выбора, а затем выполняет только вызов чтения, если он безопасен (т.е. Не будет блокироваться). Если вызов чтения будет заблокирован, вызов не будет выполнен. Вместо этого выполняется другой поток. В следующий раз, когда система времени выполнения получит контроль, она может снова проверить, чтобы убедиться, что чтение теперь безопасно. Такой подход требует переписывания частей библиотеки системных вызовов, неэффективен и неэффективен, но выбора мало. Код, размещенный вокруг системного вызова для проверки, называется курткой или оберткой.

В некоторой степени аналогично проблеме блокировки системных вызовов - проблема ошибок страниц. Мы изучим их в гл. 4. На данный момент достаточно сказать, что компьютеры могут быть настроены таким образом, что не вся программа находится в основной памяти сразу. Если программа вызывает или переходит к инструкции, которая не находится в памяти, возникает ошибка страницы, и операционная система переходит и получает недостающую команду (и ее соседей) с диска. Это называется ошибкой страницы. Процесс блокируется, когда необходимая инструкция находится и считывается. Если поток вызывает ошибку страницы, ядро, даже не зная о существовании потоков, естественно блокирует весь процесс до завершения ввода-вывода диска, даже хотя другие потоки могут быть запущены.

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

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

Другим и, вероятно, самым разрушительным аргументом в отношении потоков пользовательского уровня является то, что программисты обычно хотят потоков именно в приложениях, где потоки часто блокируются, например, на многопоточном веб-сервере. Эти потоки постоянно вызывают системные вызовы. Как только ловушка произошла с ядром для выполнения системного вызова, вряд ли больше работать на ядро, чтобы переключать потоки, если старый заблокирован, а наличие этого ядра устраняет необходимость постоянного выбора системных вызовов, которые проверьте, безопасны ли системные вызовы чтения. Для приложений, которые по существу полностью связаны с ЦП и редко блокируются, в чем же смысл иметь потоки? Никто всерьез не предлагал бы вычислять первые n простых чисел или играть в шахматы с помощью потоков, потому что ничего не получится, делая это таким образом.

Ответ 3

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

Поскольку, в конечном счете, ядро ОС отвечает за переключение контекста между "исполнительными блоками" - ваши пользовательские потоки должны быть связаны (т.е. "Отображать") с планируемым объектом ядра - потоком ядра 1.

Итак, учитывая N пользовательских потоков - вы можете использовать N потоков ядра (карта 1:1). Это позволяет вам использовать преимущества аппаратной многопроцессорной обработки ядра (работающей на нескольких процессорах) и быть довольно упрощенной библиотекой - в основном просто откладывая большую часть работы на ядро. Это, однако, делает ваше приложение переносимым между ОС, поскольку вы напрямую не вызываете функции потоков ядра. Я считаю, что POSIX Threads (PThreads) является предпочтительной реализацией * nix, и что она следует карте 1:1 (что делает ее практически эквивалентной потоку ядра). Это, однако, не гарантируется, так как это будет зависеть от реализации (основной причиной использования PThreads будет переносимость между ядрами).

Или вы можете использовать только 1 поток ядра. Это позволило бы вам работать в не-многозадачных ОС или полностью отвечать за планирование. Планирование режима пользователя Windows является примером этой карты N: 1.

Или вы можете сопоставить произвольное количество потоков ядра - карту N: M. В Windows есть Fibers, которые позволят вам отобразить N волокон в M потоков ядра и совместно планировать их. Примером этого может быть также пул потоков - N рабочих элементов для M потоков.

1: процесс имеет как минимум 1 поток ядра, который является фактической единицей выполнения. Кроме того, поток ядра должен содержаться в процессе. ОС должна запланировать запуск потока, а не процесс.

Ответ 4

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

Ответ 5

Согласно Wikipedia и Oracle, потоки пользовательского уровня фактически находятся в слое, установленном на потоках ядра; не то, что потоки ядра выполняются вместе с потоками пользовательского уровня, но, вообще говоря, единственными сущностями, которые фактически выполняются процессором/ОС, являются потоки ядра.

Например, предположим, что у нас есть программа с 2 потоками пользовательского уровня, которые сопоставлены (т.е. назначены) тем же самым потоком ядра. Иногда поток ядра запускает первый поток пользовательского уровня (и говорят, что в настоящее время этот поток ядра сопоставляется первому потоку пользовательского уровня), а в некоторых случаях поток ядра запускает второй поток пользовательского уровня. Поэтому мы говорим, что у нас есть два потока пользовательского уровня, сопоставленные с одним и тем же потоком ядра.

Как пояснение:

Ядро ОС называется kernel, поэтому потоки на уровне ядра (то есть потоки, которые ядро ​​знает о и управляет) называются потоками ядра, вызовы ядра ОС для служб можно назвать вызовами ядра и.... Единственное определенное отношение между ядром состоит в том, что они сильно связаны с ядром ОС, не более того.