Довольно частой проблемой, встречающейся у пользователей linux, является проблема с записью на флешки.
Проблема заключается в том, что когда идёт запись на флешку, скорость очень низкая (сначала, когда пишет в кэш, всё хорошо, но потом она падает до ~500-700 кбайт/с и система начинает довольно сильно тормозить. Причем тормоза настолько сильные, что иногда иксы виснут намертво на несколько минут.
Как выяснилось эмпирически, это случается из-за переключения процессоров и блокировок при использовании общего блока памяти. Логично решение указать, чтобы процессоры не переключались при обработки прерываний, на которых находятся usb.
Сначала в биосе отключаем опцию usb legacy support, заходим в систему и смотрим какие прерывания используются usb, для этого делаем:
grep usb /proc/interrupts 21: 45801 9374917 IO-APIC-fasteoi ehci_hcd:usb2, HDA Intel 22: 1 28 IO-APIC-fasteoi ohci_hcd:usb4 23: 1827 188061 IO-APIC-fasteoi ehci_hcd:usb1, ohci_hcd:usb3 |
То есть, у нас используются прерывания 21,22,23
на каждое прерывание указывается на каком процессоре оно висит, за это отвечает параметр smp_affinity
cat /proc/irq/21/smp_affinity 3 cat /proc/irq/22/smp_affinity 3 cat /proc/irq/22/smp_affinity 3 |
Теперь, что это значит
3 в шестнадцатеричной системе = 00000000.00000011 в двоичной (так как ядро скомпилировано с поддержкой 16 процессоров)
то есть обрабатыватся на CPU0, CPU1
Если нам нужно указать, чтобы обработка шла только на CPU0, то нужно задать 00000000.00000001, то есть 1
Если же нужно указать, чтобы обработка шла только на CPU1, то нужно задать 00000000.00000010, то есть 2
Теперь укажем, что будем обрабатывать на CPU0 все прерывания с висящими на них usb, естественно, всё делать нужно под рутом
echo 1 > /proc/irq/21/smp_affinity echo 1 > /proc/irq/22/smp_affinity echo 1 > /proc/irq/23/smp_affinity |
Так как прерывания могут быть разными, то нужно либо вручную их узнавать и указывать, или написать скрипт и добавить его в автозагрузку.
Собственно, вот скрипт, который проверит прерывания, на которых висят usb и указывает, какой процессор выполняет работу с ними. Нужно скопировать его в /usr/local/bin и засунуть его в загрузку системы (например, прописать /usr/local/bin/setusbwrite в /etc/init.d/usb-flash), а так же дать скрипту права на запуск.
#!/bin/sh
for interruption in `grep usb /proc/interrupts| awk '{print $1}'| sed -e 's/\://g'` ; do |