Вопрос или проблема
На основе Limit file IO speed я создал https://git.data.coop/tange/tangetools/src/branch/master/iothrottle
Это работает для некоторых программ:
iothrottle -i 10M cat foo > bar # Да, здесь можно просто использовать pv
iothrottle -o 1M ffmpeg -i foo.mp3 foo.wav
iothrottle -o 1M cp -a foodir /other/fs/foodir
Это не работает:
iothrottle -o 1M cp -a foodir /same/fs/foodir
потому что на одной файловой системе cp
использует один вызов copy_file_range
на файл.
Меня устраивает это ограничение.
Это также не работает для seq
. Когда я запускаю strace seq 100000
, я получаю:
write(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
write(1, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 4096) = 4096
write(1, "2680\n2681\n2682\n2683\n2684\n2685\n26"..., 4096) = 4096
write(1, "499\n3500\n3501\n3502\n3503\n3504\n350"..., 4096) = 4096
write(1, "18\n4319\n4320\n4321\n4322\n4323\n4324"..., 4096) = 4096
write(1, "7\n5138\n5139\n5140\n5141\n5142\n5143\n"..., 4096) = 4096
write(1, "\n5957\n5958\n5959\n5960\n5961\n5962\n5"..., 4096) = 4096
write(1, "6776\n6777\n6778\n6779\n6780\n6781\n67"..., 4096) = 4096
write(1, "595\n7596\n7597\n7598\n7599\n7600\n760"..., 4096) = 4096
write(1, "14\n8415\n8416\n8417\n8418\n8419\n8420"..., 4096) = 4096
write(1, "3\n9234\n9235\n9236\n9237\n9238\n9239\n"..., 3838) = 3838
Таким образом, кажется, что он вызывает write
(а не какой-то mmap
или другую магию), и, следовательно, должен работать.
Но когда я запускаю: IOTHROTTLE_DEBUG=1 iothrottle -o 1M seq 10000 >/dev/null
, я получаю:
init called: default read_limit=0, write_limit=0
IOTHROTTLE_READ=0
IOTHROTTLE_WRITE=1048576
Final read_limit=0, write_limit=1048576
allowed: 608 written: 0
allowed: 617 written: 0
Это говорит мне, что iothrottle
перехватывает только 2 вызова write
.
Что я упускаю?
Ответ или решение
Понимание того, почему не удается перехватить вызов write
в команде seq
, предполагает глубокий анализ работы системы и метода перехвата системных вызовов. Ваше желание использовать iothrottle для ограничения скорости ввода-вывода данных с помощью команды seq
подразумевает необходимость в корректном отслеживании всех вызовов write
. Ниже подробно рассмотрим возможные причины, почему это может не работать так, как ожидается.
Проблемы перехвата системных вызовов
-
Библиотеки и обертки: Возможно, iothrottle не охватывает все возможные способы вызова функций
write
, что может быть связано с библиотеками, используемыми в программеseq
. Например, некоторые системные вызовы могут выполняться не напрямую, а через стандартные функции ввода-вывода, такие какfwrite
, которые могут не захватываться вашим инструментом, если они реализованы через buffered I/O. -
Оптимизации ядра: Проверьте, нет ли оптимизаций, связанных с выводом на консоль или перенаправлением в
/dev/null
. Некоторые программы могут работать по-разному в зависимости от конечного местоположения вывода, что особенно актуально для высоко оптимизированных системных утилит, таких какseq
. -
Проблемы с библиотеками: Если iothrottle зависит от замены стандартных библиотек динамического связывания (
LD_PRELOAD
), это также может быть причиной. Некоторые системные утилиты могут игнорировать эти параметры из-за безопасности или по другим причинам.
Анализ вывода и логирования
-
Ограниченное количество вызовов
write
: Вы заметили, что только 2 вызоваwrite
отображаются в логах iothrottle, хотя strace демонстрирует больше. Это может указывать на проблему с обработкой вызовов в iothrottle. Убедитесь, что все необходимые вызовы действительно перехватываются. -
Проблемы совместимости: Возможно, имеются проблемы с версией iothrottle или его совместимостью с текущим окружением и используемой версией ядра или утилит.
Рекомендации по решению
- Дополнительные проверки и тесты: Используйте другие утилиты мониторинга, такие как
lsof
илиdstat
, для проверки, отслеживаются ли все вызовы корректно. - Кодовая база и тестирование: Проанализируйте исходный код iothrottle, чтобы выявить, какие сценарии он может пропускать. Проведите тестирование с разными конфигурациями окружения.
- Обновления и патчи: Убедитесь, что используете последнюю версию iothrottle и, если возможно, внесите необходимые изменения для расширения функциональности.
Если у вас возникнут дальнейшие вопросы или потребуется помощь с более детальными аспектами реализации, рассмотрите возможность обсуждения с экспертами в сообществе открытого ПО, специализирующимися на перехвате системных вызовов.