Я думаю, что пример в реальном мире устранит путаницу, поэтому давайте посмотрим, как это делается в Linux.
Прежде всего, Linux не проводит различия между процессом и потоком, объект, который может быть запланирован, называется задачей в Linux и представлен task_struct. Поэтому всякий раз, когда вы выполняете системный вызов fork(), создается новая task_struct, которая содержит данные (или указатель), связанные с новой задачей.
Итак, в мире Linux поток ядра означает объект task_struct (структура). Поскольку планировщик знает об этих объектах, которые могут быть назначены различным ЦП (логическим или физическим). Другими словами, если вы хотите, чтобы планировщик Linux планировал ваш процесс, вы должны создать task_struct.
Пользовательский поток - это то, что поддерживается и управляется за пределами ядра с помощью некоторой среды исполнения (EE с этого момента), такой как JVM. Эти EE предоставят вам некоторые функции для создания новых потоков.
Теперь давайте ответим на ваш вопрос
why a user thread must always be mapped to a specific kernel thread.
Допустим, вы создали несколько потоков с помощью EE.в конечном итоге они должны выполняться процессором, и из приведенного выше объяснения мы знаем, что вы (поток) должны иметь task_struct, чтобы назначить некоторый процессор. Вот почему отображение должно существовать. Обязанность вашей EE создавать task_structs.
Если ваш EE использует много моделей, то он создаст только один task_struct для всех потоков, и он запланирует все эти потоки на этот task_struct. Подумайте об этом, так как есть один CPU (task_struct) и многие процессы (потоки, созданные в EE), ваша операционная система (EE) будет мультиплексировать эти процессы на одном CPU.
Если он использует одну модель, чем будет один task_struct для каждого потока, созданного в EE. Поэтому, когда вы создаете новый поток в своем EE, в ядре создается соответствующий task_struct.
Windows делает все по-другому (процесс и поток разные), но общая идея остается той же, что и поток ядра, это объект, который планировщик CPU рассматривает для назначения, поэтому потоки пользователей должны отображаться в соответствующие потоки ядра (если вы хотите, чтобы CPU выполнить их).