FlexSC: новый механизм системных вызовов в ядре Linux

Разное > История

Эта статья рассказывает о новом механизме системных вызовов ядра Linux, который позволяет существенно сократить время исполнения приложений без необходимости их модификации.

FlexSC: новый механизм системных вызовов в ядре <strong class=Linux" />

Уже 30 лет системные вызовы остаются стандартным и, в большинстве операционных систем, единственным способом коммуникации между приложениями и ядром операционной системы. С помощью системных вызовов процессы получают возможность порождать потомков, читать и записывать файлы, инициировать сетевые соединения и делать все, что требуется для полноценной работы.

Однако сам механизм системных вызовов не лишен многих недостатков, самый сильный из которых заключается в огромном оверхеде, который накладывается на систему исполнения из-за необходимости переключения контекста.

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

Ситуация такова, что на бесцельное расходование ресурсов может уйти 50% и даже больше процентов от общего времени исполнения программы, при том, что каждый системный вызов будет "тормозить" процессор за счет нивелирования производимых им оптимизаций.

Создатели механизма FlexSC предлагают решить эту проблему с помощью так называемых "системных вызовов без исключений". Суть этой технологии состоит в том, чтобы научить ядро группировать системные вызовы и выполнять их не поочередно, а все сразу, что в теории позволит существенно сократить общее количество переключений контекста и, таким образом, поднять производительность приложений.

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

Реализация FlexSC

Реализация идеи "системных вызовов без исключений" в ядре Linux состоит из трех частей:

  • Новый интерфейс между ядром и пространством пользователя, выполненный в виде нескольких страниц памяти, доступных для чтения и записи как приложениям, так и ядру;
  • Многопоточная система исполнения запрошенных системных вызовов;
  • Два новых системных вызова, используемых для инициализации подсистемы FlexSC и ее включения.

Приложение, пожелавшее использовать механизм FlexSC, делает системный вызов (классический) flexsc_register(), в результате которого ядро выделяет нескольких страниц памяти и создает новый внутриядерный поток, который в будущем будет обслуживать интерфейс FlexSC для этого приложения. Далее управление возвращается обратно пользовательскому процессу, который теперь имеет два пути взаимодействия с ядром: стандартный интерфейс системных вызовов и механизм FlexSC.

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

Система будет работать в этом режиме до тех пор, пока процесс не достигнет той точки, когда он не сможет продолжить исполнение без выполнения одного или всех ранее запрошенных системных вызовов (например, попытается прочитать ранее открытый файл). В этом случае процесс должен послать запрос на их выполнение. Для этого он выполняет системный вызов (классический) flexsc_wait(), который передает управление FlexSC-потоку внутри ядра.

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

После выполнения всех запросов управление возвращается вызывающему процессу, который извлекает результаты исполнения системных вызовов из разделяемой памяти и продолжает работу.

FlexSC-Threads

Глупо полагать, что кто-то из программистов начнет использовать такой интерфейс. Он не слишком удобен, чреват ошибками и, к тому же, привязывает приложение к конкретной редакции ядра Linux. Поэтому авторы создали библиотеку FlexSC-Threads, которая эмулирует интерфейс стандартных системных вызовов поверх механизма FlexSC. Она представляет собой POSIX-совместимую библиотеку потоков (NPTL), которая подменяет стандартные libc-функции, служащие интерфейсом к  системными вызовами, собственными аналогами, позволяя использовать преимущества FlexSC без модификации существующих приложений.

Эмуляция стандартного интерфейса системных вызовов для всех приложений не дала бы сколько-нибудь значительного выигрыша просто из-за архитектуры самих приложений, написанных в расчете на синхронность системных вызовов (взаимозависимые блокирующие системные вызовы в большинстве приложений идут друг за другом: open(), read(), close(), поэтому их так или иначе придется выполнять последовательно). Однако для многопоточных приложений выигрыш оказывается значительным, так как FlexSC позволяет группировать исполнение системных вызовов многих потоков (которые просто по определению не могут быть взаимосвязанными).

Выводы

Судя по тому, каких результатов удалось добиться создателям технологии, FlexSC очень перспективный проект. Только лишь за счет внедрения технологии в ядро, без каких либо модификаций приложений, им удалось добиться прироста производительности Apache на 116%, MySQL - на 40% и BIND - на 105%. Огорчает только то, что исходный код технологии еще не был показан общественности. Будем надеяться, что это дело времени.

Комментарии
]]> ipv6 ready Kiev LUGLinux4MeНостальгияЛичный сайт skeletora ]]>