Назад к вопросам
Principal
221
questionbank
Какие сущности присутствуют в планировщике?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
В планировщике Golang (M) присутствуют следующие сущности:
- M (Machine): Представляет собой поток операционной системы. Отвечает за исполнение G-кода на процессоре. M забирает G из локальной очереди P или обходной очереди.
- P (Processor): Логический процессор (контекст). Содержит локальную очередь готовых к выполнению G. P привязан к M, и только один M может быть привязан к P в любой момент времени. Количество P по умолчанию равно
GOMAXPROCS. - G (Goroutine): Легковесный поток выполнения. Представляет собой конкурентную функцию или метод. G исполняется на P.
// Представление горутины, содержит стэк, указатель на функцию и состояние.
type g struct {
stack stack // stask описывает стек горутины
stackguard uintptr // для проверки стэка
stackbase uintptr // база стэка
sched stato // для планировщика
// ... другие поля
}
// Представление логического процессора, имеет свою локальную очередь горутин
type p struct {
id int // ID логического процессора
runq []*g // локальная очередь горутин
// ... другие поля
}
// Представление потока ОС, исполняет горутины с помощью p
type m struct {
g0 *g // горутина для планировщика
curg *g // текущая горутина
p *p // привязанный логический процессор
// ... другие поля
}
Взаимодействие между сущностями следующее:
- Горутины (G) помещаются в локальные очереди логических процессоров (P).
- Потоки ОС (M) берут P и из их локальных очередей забирают G для выполнения на процессоре.
- Если локальная очередь P пуста, M может попытаться украсть G из локальной очереди другого P (work-stealing).
- При блокирующих системных вызовах, M отвязывается от P, и другой M может занять этот P для выполнения других G. Заблокированный G остается привязанным к отвязавшемуся M.
// Упрощенная иллюстрация планирования:
// m0 ---(привязан к)---> p0 ---> [g1, g2, g3] (локальная очередь)
// m1 ---(привязан к)---> p1 ---> [g4, g5]
// m2 (свободен) ---> ищет p0 или p1 для steal
Таким образом, планировщик Golang эффективно использует доступные ядра процессора, распределяя выполнение легковесных горутин между потоками ОС через логические процессоры.