Вопрос или проблема
У меня есть сетевая карточка Intel i210, которая поддерживает 4 объединенных fifo канала. Я хочу распределить обработчики прерываний от этих каналов среди первых 4 ядер в моей системе.
Я пробовал добавить правило udev, которое будет срабатывать на событие ADD от ядра:
/etc/udev/rules.d/98-i210-network-card.rules
:
ACTION=="add", SUBSYSTEM=="net", DEVPATH=="/devices/...", RUN+="/usr/local/bin/spread-i210-irq-handlers.sh"
/usr/local/bin/spread-i210-irq-handlers.sh
:
set -exuo pipefail
# распределить IRQ по CPU 0-3
proc_curr=0
proc_max=4
for irq_path in /sys/$DEVPATH/msi_irqs/*; do
irq=$(basename $irq_path)
echo $proc_curr > /proc/irq/$irq/smp_affinity_list
proc_curr=$(( (proc_curr + 1) % proc_max ))
done
Но проблема в том, что файл /proc/irq/$irq/smp_affinity_list
в этот момент не существует.
Как правильно статически настроить smp_affinity_list для какого-либо устройства?
Ответ или решение
Для статической настройки параметра smp_affinity
для обработчиков прерываний (IRQ) сетевой карты Intel i210 на Linux, вы можете использовать несколько методов, чтобы убедиться, что настройки применяются корректно после добавления устройства.
1. Использование udev
правил
Ваше текущее правило udev
имеет правильную направленность, однако оно не учитывает, что пункт назначения для установки значений smp_affinity
может быть недоступен в момент выполнения скрипта. Это может происходить из-за того, что файл /proc/irq/$irq/smp_affinity_list
не создан в момент активации правила.
Корректировка вашего решения:
Чтобы это исправить, вы можете использовать задержку в скрипте или осуществить проверку наличия файла перед попыткой записи в него. Вот подправленная версия вашего скрипта:
#!/bin/bash
set -exuo pipefail
# spread IRQs across CPUs 0-3
proc_curr=0
proc_max=4
for irq_path in /sys/$DEVPATH/msi_irqs/*; do
irq=$(basename $irq_path)
# Проверяем, что сможем записать, обязательно используем цикл для ожидания
while [ ! -e /proc/irq/$irq/smp_affinity_list ]; do
sleep 1
done
echo $proc_curr > /proc/irq/$irq/smp_affinity_list
proc_curr=$(( (proc_curr + 1) % proc_max ))
done
2. Альтернативный подход с использованием systemd
службы
Если вы хотите более устойчивое решение, можно создать системную службу, которая будет необходима для периодического выполнения скрипта настройки smp_affinity
.
- Создайте новый сервис-файл:
sudo nano /etc/systemd/system/spread-i210-irq-handlers.service
Добавьте в него следующее содержимое:
[Unit]
Description=Spread IRQ handlers across CPU cores
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/spread-i210-irq-handlers.sh
[Install]
WantedBy=multi-user.target
- Включите службу, чтобы она запускалась при каждой загрузке:
sudo systemctl enable spread-i210-irq-handlers.service
- Запустите службу:
sudo systemctl start spread-i210-irq-handlers.service
3. Мониторинг и отладка
После изменения конфигурации вам стоит проверить, действительно ли обработчики прерываний распределены между ядрами CPU. Это можно сделать с помощью команды:
cat /proc/interrupts
После выполнения этих шагов ваша система должна корректно конфигурировать smp_affinity
для IRQ, обеспечивая равномерное распределение нагрузки между ядрами процессора.