Как работает sched_setaffinity ()? - PullRequest
12 голосов
/ 20 апреля 2009

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

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

Итак, я скачал исходники ядра Linux 2.6.27.19 .

Я сделал 'grep' для строк, содержащих этот системный вызов, и получил 91 результат. Не перспективно.

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

Я знаком с тем, как работают одноядерные и однопоточные программы. Можно выполнить команду 'jmp foo', и это в основном устанавливает IP в адрес памяти метки 'foo'. Но когда у вас несколько ядер, нужно сказать: «получить следующую инструкцию по адресу памяти foo и установить указатель инструкции для номер ядра 2 , чтобы начать выполнение там».

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

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

Ответы [ 4 ]

9 голосов
/ 20 апреля 2009

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

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

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

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

4 голосов
/ 20 апреля 2009

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

1 голос
/ 20 апреля 2009

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

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

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

0 голосов
/ 03 декабря 2009
...