2009-12-07 2 views
10

Много раз я читал/слышал аргумент, что многие системные вызовы и т. Д. Были бы неэффективными, поскольку приложение делает переключатель режима, т.е. переходит из режима пользователя в режим ядра и после выполнения системный вызов начинает выполнение в пользовательском режиме, снова переключая переключатель режима.Что такое накладные расходы, связанные с переключением режимов

Мой вопрос в том, что накладные расходы переключателя режима? Сбой кэша процессора или недействительные записи tlb или что происходит, что вызывает накладные расходы?

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

Если его возможно, пожалуйста, предоставить некоторую информацию о конкретной * NIX платформы как Linux, FreeBSD, Solaris и т.д.

С уважением

Лали

ответ

8

Там не должно быть никакого кэша процессора или TLB флеш на простой режим переключатель.

Быстрый тест говорит мне, что на моем ноутбуке Linux требуется около 0,11 микросекунды для процесса пользовательского пространства, чтобы выполнить простой системный вызов, который выполняет незначительный объем работы, кроме переключения в режим ядра и обратно. Я использую getuid(), который копирует только одно целое из структуры в памяти. strace подтверждает, что syscall повторяется MAX раз.

#include <unistd.h> 
#define MAX 100000000 
int main() { 
    int ii; 
    for (ii=0; ii<MAX; ii++) getuid(); 
    return 0; 
} 

Это занимает около 11 секунд на моем ноутбуке, измеренная с помощью time ./testover и 11 секунд деленное на 100 млн дает 0,11 микросекунды.

Технически это два переключателя режима, поэтому, предположим, вы можете утверждать, что один переключатель режимов занимает 0.055 микросекунды, но односторонний переключатель не очень полезен, поэтому я бы рассмотрел номер там и обратно быть более актуальным.

1

Существует много способов сделать переключатель режимов на x86-процессорах (которые я принимаю здесь). Для функции, называемой пользователем, обычным способом является выполнение прыжка задачи или вызова (называемого «Задания задач» и «Вызовы»). Оба они включают в себя переключатель Task (эквивалент контекстного переключателя). Добавьте к этому немного обработки перед вызовом, стандартную проверку после вызова и возврат. Это округляет минимум до безопасного переключателя режима.

Что касается времени Эрика, я не эксперт по Linux, но в большинстве ОС я имел дело с простыми системными данными кеша (если это можно сделать безопасно) в пользовательском пространстве, чтобы избежать этих накладных расходов. И мне кажется, что getuid() будет основным кандидатом для такого кэширования данных. Таким образом, время Эрика может быть скорее отражением накладных расходов на обработку перед переключением в пользовательском пространстве, чем что-либо еще.

+1

Не происходит кэширование данных; поэтому я использовал strace для проверки того, что происходит системный вызов. Syscall, по определению, является вызовом в пространство ядра. –

+1

Кроме того, ваше утверждение о том, что переключатель режима эквивалентен контекстному переключателю, неверен. Переключатель контекста включает в себя замену всего состояния процессора и таблиц страниц; это значительная работа, которая не требуется для системных вызовов. Syscall - это простое программное прерывание (сборка x86 «int $ 0x80») –

+0

Итак, в syscall есть только преамбула и инструкция INT? – Juice

Смежные вопросы