Два разных пользовательских процесса имеют разные виртуальные адресные пространства. Поскольку виртуальные сопоставления физических адресов различаются, кэш 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 & 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-4 ГБ все равно будет вне диапазона.)
Какие могут быть ошибки? Например, предположим, что вы реализуете быструю сортировку и у вас есть два указателя, a
и b
, указывающие на начало и конец конца массива. Если вы выберете середину в качестве оси с (a+b)/2
, она будет работать до тех пор, пока оба адреса меньше 2 ГБ, но если они оба выше, то при добавлении возникнет целочисленное переполнение, и результат будет вне массива. (Правильное выражение a+(b-a)/2
.)
Кроме того, 32-битный Linux с разделением по умолчанию на ядро 3G / 1G для пользователя / ядра исторически запускал программы с их стеком, расположенным в диапазоне 2-3 ГБ, поэтому любые такие ошибки в программировании, вероятно, были бы быстро удалены , 64-битный Linux предоставляет 32-битным программам доступ к 0-4 ГБ.