Как работает sched_setaffinity()?
Я пытаюсь понять, как работает linux syscall sched_setaffinity(). Это продолжение моего вопроса здесь.
У меня это руководство, в котором объясняется, как использовать syscall и имеет довольно аккуратный (рабочий!) пример.
Итак, я загрузил Linux 2.6.27.19 источники ядра.
Я сделал "grep" для строк, содержащих этот syscall, и получил 91 результат. Не обещаю.
В конечном счете, я пытаюсь понять, как ядро может установить указатель инструкции для определенного ядра (или процессора.)
Я знаю, как работают одноядерные однопоточные программы. Можно было бы выпустить инструкцию jmp foo, и это в основном устанавливает IP-адрес в адрес памяти метки "foo". Но когда у вас есть несколько ядер, нужно сказать: "Принесите следующую команду в адрес памяти foo и установите указатель инструкции для ядра номер 2, чтобы начать там выполнение".
Где в коде сборки мы указываем, какое ядро выполняет эту операцию?
Вернуться к коду ядра: что здесь важно? Файл 'kernel/sched.c' имеет функцию sched_setaffinity(), но возвращает тип long, который не соответствует его странице руководства. Итак, что здесь важно? На каком из этих модулей отображаются инструкции по сборке? Какой модуль читает "task_struct", глядя на член "cpus_allowed", а затем переводим его в инструкцию? (Я также просмотрел источник glibc, но я думаю, что он просто делает вызов кода ядра для выполнения этой задачи.)
Ответы
Ответ 1
sched_setaffinity()
просто сообщает планировщику, что процессоры - это процесс/поток, разрешенный для запуска, а затем вызывает перерасчет.
Планировщик фактически работает на каждом из процессоров, поэтому у него появляется возможность решить, какую задачу выполнить дальше на этом конкретном процессоре.
Если вам интересно, как вы можете называть какой-то код на других процессорах, я предлагаю вам взглянуть на smp_call_function_single()
. Если мы хотим вызвать что-то на другом CPU, это вызывает generic_exec_single()
. Последний просто добавляет функцию в целевую очередь целевого процессора и заставляет перепланировать через некоторый IPI (если очередь была пуста).
Нижняя строка: нет реального варианта SMP команды _jmp_
. Вместо этого код, работающий на других ЦП, взаимодействует для выполнения задачи.
Ответ 2
Я думаю, что вы не понимаете, что ядро работает на всех ядрах процессора. При каждом прерывании таймера (~ 1000 в секунду) планировщик запускается на каждом CPU и выбирает процесс для запуска. Нет ни одного процессора, который каким-то образом подсказывает другим начать процесс. sched_setaffinity()
работает, просто устанавливая флаги в процессе. Планировщик читает эти флаги и не будет запускать этот процесс на своем CPU, если он установлен не.
Ответ 3
Где в коде сборки мы указываем, какое ядро выполняет эту операцию?
Здесь нет сборки. Каждая задача (поток) назначается одному процессору (или ядру в ваших терминах) за раз. Чтобы перестать работать на заданном CPU и возобновить работу на другом, задача должна " migrate" (также this). Когда задача переносится с одного процессора на другой, планировщик выбирает процессор, который более неактивен среди процессоров, разрешенных sched_setaffinity()
.
Нет никаких инструкций по сборке магии. Ядро имеет более низкоуровневое представление о оборудовании, каждый процессор представляет собой отдельный объект, очень отличающийся от того, как он выглядит для процессов пользовательского пространства (в пользовательском пространстве процессоры почти невидимы).
Ответ 4
Проверьте это: B Руководство по программированию операционной системы