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

Я обычно использую что-то вроде этого:

>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
...     s= s.replace(c,"")
...
>>> s
'string With Punctuation'
19
задан Mel 4 September 2017 в 09:10
поделиться

6 ответов

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

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

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

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


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

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

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

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

22
ответ дан 30 November 2019 в 04:16
поделиться
8
ответ дан 28 September 2019 в 02:35
поделиться

Windows (like any OS) is a lot more than the kernel + drivers.

Your application relies on a lot of OS services that do not just exist in kernel space. Существует множество буферов, дескрипторов и всевозможных ресурсов, которые можно сопоставить с собственным адресным пространством вашего процесса. Каждый раз, когда вы вызываете функцию Win32 API, которая возвращает, скажем, дескриптор окна или кисть, эти вещи должны быть размещены где-то в вашем процессе. Итак, часть Windows работает в ядре, да, другие части запускаются в своих собственных процессах пользовательского режима, а некоторые, к которым вашему приложению требуется прямой доступ, отображаются в ваше адресное пространство. Отчасти этого трудно избежать, но важным дополнительным фактором является производительность. Если бы каждый вызов Win32 требовал переключения контекста, это сильно снизило бы производительность. Если некоторые из них могут обрабатываться в пользовательском режиме, потому что данные, на которые они полагаются, уже сопоставлены с вашим адресным пространством, переключения контекста можно избежать, и вы сэкономите немало циклов процессора. Я считаю, что Linux по умолчанию устанавливает только 1 ГБ для ОС.

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

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

3
ответ дан 30 November 2019 в 04:16
поделиться

I believe the best answer is that the OS designers felt that by the time you would have to care, people would be using 64-bit Windows.

But here's a better discussion.

1
ответ дан 30 November 2019 в 04:16
поделиться

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

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

2
ответ дан 30 November 2019 в 04:16
поделиться

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

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

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

0
ответ дан 30 November 2019 в 04:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: