Как работает функция sched setaffinity ()?


Я пытаюсь понять, как работает linux syscall sched_setaffinity (). Это продолжение моего вопроса здесь.

У меня есть это руководство, которое объясняет, как использовать syscall и имеет довольно аккуратный (рабочий!) образец.

Поэтому я загрузил Linux 2.6.27.19 исходники ядра.

Я сделал "grep" для строк, содержащих этот syscall, и получил 91 результат. Ничего не обещаю.

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

Я знаком с тем, как работают одноядерные программы с одним потоком. Можно было бы выдать инструкцию 'jmp foo', и это в основном устанавливает IP-адрес в адрес памяти метки 'foo'. Но когда у вас есть несколько ядер, вы должны сказать " fetch The next instruction at memory address foo, и установить указатель инструкции для core number 2 , чтобы начать выполнение там."

Где, в сборке код, мы указываем, какое ядро выполняет эту операцию?

Вернемся к коду ядра: что здесь важно? Файл ' kernel/sched.c 'имеет функцию sched_setaffinity (), но возвращает тип "long", что несовместимо с его справочной страницей. Так что же здесь важно? Какой из этих модулей показывает выданные инструкции по сборке? Какой модуль читает 'task_struct', смотрит на' cpus_allowed ' член, а затем переводит его в инструкцию? (У меня тоже есть пролистал исходный код glibc - но я думаю, что он просто вызывает код ядра для выполнения этой задачи.)

4 12

4 ответа:

sched_setaffinity() просто сообщает планировщику, на каких процессорах разрешено работать этому процессу / потоку, а затем вызывает повторное расписание.

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

Если вас интересует, как вы можете вызвать некоторый код на других процессорах, я предлагаю вам взглянуть на smp_call_function_single(). В случае, если мы хотим вызвать что-то на другом процессоре, это вызывает generic_exec_single(). Последний просто добавляет функцию к Очередь вызовов целевого процессора и заставляет перепланировать через некоторый IPI материал (если очередь была пуста).

Суть такова: нет никакого фактического варианта SMP инструкции _jmp_. Вместо этого код, запущенный на других процессорах, взаимодействует для выполнения задачи.

Я думаю, что вы не понимаете, что ядро работает на всех ядрах процессора. При каждом прерывании таймера (~1000 в секунду) планировщик запускается на каждом процессоре и выбирает процесс для запуска. Нет ни одного процессора, который каким-то образом говорит другим, чтобы запустить процесс. sched_setaffinity() работает, просто устанавливая флаги на процесс. Планировщик считывает эти флаги и не будет запускать этот процесс на своем процессоре, если он не установлен.

Где в ассемблерном коде мы указываем, какое ядро выполняет эту операцию?

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

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