Подтвердить что ты не робот

Почему Windows резервирует 1 Гбит (или 2 Гб) для своего системного адресного пространства?

Известно, что приложения Windows обычно имеют 2 Гбит частного адресного пространства в 32-битной системе. Это пространство может быть расширено до 3Gb с помощью переключателя /3Gb.

Операционная система оставляет за собой оставшиеся 4Gb.

Мой вопрос: ПОЧЕМУ?

Код, работающий в режиме ядра (т.е. код драйвера устройства), имеет собственное адресное пространство. Почему, помимо эксклюзивного адресного пространства 4Gb, операционная система все еще хочет зарезервировать 2 Гбит каждого процесса в пользовательском режиме?

Я думал, что причиной является переход между вызовом режима пользователя и режима ядра. Например, для вызова NtWriteFile потребуется адрес для процедуры диспетчеризации ядра (следовательно, система резервирует 2Gb в каждом приложении). Но, используя SYSENTER, не является системным номером службы, достаточным для кода режима ядра, чтобы узнать, какая функция/служба вызывается?

Если бы вы могли пояснить мне, почему так важно, чтобы операционная система принимала 2Gb (или 1Gb) каждого процесса пользовательского режима.

4b9b3361

Ответ 1

Два разных пользовательских процесса имеют разные виртуальные адресные пространства. Поскольку сопоставления физических и виртуальных адресов различны, кеш TLB недействителен при переключении контекстов из одного пользовательского процесса в другой. Это очень дорого, так как без адреса, уже кэшированного в TLB, любой доступ к памяти приведет к ошибке и прогулке PTE s.

Syscalls включает два контекстных переключателя: user → kernel, а затем kernel → user. Чтобы ускорить это, обычно резервируется верхнее 1 ГБ или 2 ГБ виртуального адресного пространства для использования ядра. Поскольку виртуальное адресное пространство не изменяется в этих контекстных коммутаторах, никакие сбросы TLB не нужны. Это активируется битом пользователя/супервизора в каждом PTE, что гарантирует, что память ядра доступна только в ядерном пространстве; пользовательское пространство не имеет доступа, хотя таблица страниц одинакова.

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

Linux на x86 однажды поддерживал режим, известный как "4G/4G split". В этом режиме пользовательское пространство имеет полный доступ ко всему виртуальному адресному пространству 4 ГБ, а ядро ​​также имеет полное виртуальное адресное пространство 4 ГБ. Стоимость, как упоминалось выше, заключается в том, что для каждого сценария требуется сброс TLB, а также более сложные процедуры для копирования данных между пользователем и памятью ядра. Это было измерено, чтобы наложить до 30% штрафных санкций.


Времена изменились с тех пор, как этот вопрос был изначально спрошен и ответил: 64-битные операционные системы теперь намного более распространены. В текущих операционных системах на x86-64 для пользовательских программ разрешены виртуальные адреса от 0 до 2 47 -1 (0-128TB), а ядро ​​постоянно находится внутри виртуальных адресов от 2 47 & times; (2 17 -1) до 2 64 -1 (или от -2 47 до -1, если вы обрабатываете адреса как знаковые целые числа).

Что произойдет, если вы запустите 32-разрядный исполняемый файл в 64-битной Windows? Вы могли бы подумать, что все виртуальные адреса от 0 до 2 32 (0-4 ГБ) будут легко доступны, но чтобы избежать выявления ошибок в существующих программах, 32-разрядные исполняемые файлы по-прежнему ограничены 0- 2 ГБ, если они не перекомпилированы с помощью /LARGEADDRESSAWARE. Для тех, кто есть, они получают доступ к 0-4 ГБ. (Это не новый флаг, тот же, примененный в 32-разрядных ядрах Windows, работающих с ключом /3GB, который изменил по умолчанию 2G/2G пользователь/ядро, разделенное на 3G/1G, хотя, конечно, 3-4GB все равно будет вне диапазона.)

Какие могут быть ошибки? В качестве примера предположим, что вы реализуете quicksort и имеете два указателя, a и b, указывающие на начало и конец конца массива. Если вы выберете середину как ось с (a+b)/2, она будет работать до тех пор, пока оба адреса будут ниже 2 ГБ, но если они оба выше, то добавление столкнется с переполнением целочисленного числа, и результат будет вне массива. (Правильное выражение a+(b-a)/2.)

В отличие от 32-разрядного Linux с его дефолтом по умолчанию /3G/1G по умолчанию он исторически запускал программы со своим стеком, расположенным в диапазоне 2-3 ГБ, поэтому любые такие ошибки программирования, вероятно, будут быстро удалены, 64-разрядный Linux дает 32-битным программам доступ к 0-4 ГБ.

Ответ 3

Windows (как и любая ОС) намного больше, чем драйверы ядра +.

Ваше приложение опирается на множество сервисов ОС, которые не просто существуют в пространстве ядра. Существует множество буферов, ручек и всевозможных ресурсов, которые могут быть сопоставлены с собственным адресным пространством вашего процесса. Всякий раз, когда вы вызываете функцию API Win32, которая возвращает, например, дескриптор окна или кисть, эти вещи должны быть размещены где-то в вашем процессе. Таким образом, часть Windows работает в ядре, да, другие части работают в собственных процессах пользовательского режима, а некоторые, к которым ваше приложение нуждается в прямом доступе, сопоставляются с вашим адресным пространством. Частично этого трудно избежать, но важным дополнительным фактором является производительность. Если для каждого вызова Win32 необходим контекстный переключатель, это будет серьезный удар по производительности. Если некоторые из них могут обрабатываться в usermode, потому что данные, на которые они полагаются, уже сопоставлены с вашим адресным пространством, избегается контекстный переключатель, и вы сохраняете довольно много циклов процессора.

Таким образом, для любой ОС требуется некоторое количество адресного пространства. Я полагаю, что Linux по умолчанию устанавливает только 1 ГБ для ОС.

Причина, по которой MS устроилась на 2 ГБ с Windows, объяснялась однажды в блоге Raymond Chen. У меня нет ссылки, и я не могу вспомнить детали, но решение было принято, потому что Windows NT изначально была нацелена на процессоры Alpha, а на Alpha's была какая-то ДЕЙСТВИТЕЛЬНО хорошая причина сделать 50/50 Трещина.;)

Это было связано с поддержкой Alpha для 32, а также с 64-битным кодом.:)

Ответ 4

Код, работающий в режиме ядра (например, код драйвера устройства), имеет собственное адресное пространство.

Нет, нет. Он должен разделить это адресное пространство с частью пользовательского режима процесса на процессорах x86. Поэтому ядро ​​должно резервировать пространство достаточно и ограничить адресное пространство.

Ответ 5

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

Но здесь лучшее обсуждение.

Ответ 6

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

Процессор Intel 8086 имел архитектуру смещения сегмента для памяти, дающую 20-битные адреса памяти и, следовательно, общую адресуемую физическую память объемом 1 МБ.

В отличие от конкурирующих процессоров эпохи, таких как Zilog Z80, Intel 8086 имел только одно адресное пространство, которое должно было учитывать не только электронную память, но и все коммуникации ввода/вывода с такими незначительными периферийными устройствами, как клавиатура, последовательные порты, порты принтера и видео. (Для сравнения, Zilog Z80 имел отдельное адресное пространство ввода/вывода с выделенными кодами операций для доступа)

Необходимость пространства для постоянно растущего диапазона периферийных расширений привела к первоначальному решению сегментировать адресное пространство в электронной памяти от 0 до 40 Кбайт и "другие вещи" (ввод/вывод, ROMS, видеопамять и т.д.), от 640 К до 1 МБ.

По мере того, как линия x86 росла и развивалась, а ПК развивались вместе с ними, использовались аналогичные схемы, заканчивающиеся на сегодняшнее разделение 2G/2G адресного пространства 4G.