LINUX.ORG.RU

Разное адресное пространство


0

0

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

В ядре Linux адресные пространства пользователя и ядра «разные». Эта «разница» достигается за счет какого механизма основанного на регистре CR3. Собсно нужно понять что за механизм и как оно функционирует :) Ваще не знаю с какой стороны к этому подойти к понимание этого вопроса ))


Это называется страничный механизм распределения памяти. Если интересно про разделение памяти между процессами - почитай про виртуальное адресное пространство. Верхние 256 записей в каталоге таблиц страниц отданы под ядро, остальные отдаются под нужды процессов. По этой причине вместо 4 гигов на 32-битной системе ты получишь только 3 гига без ремаппинга. Оно?

MuZHiK-2 ★★★★
()

На х86_32 архитектуре ядро работает в 4Gb виртуальном адресном пространстве, адреса выше 0xC0000000 - адреса ядра. Защита памяти организована на сегментной и страничной адресациях, лимит у обоих от 0x00000000 до 0xFFFFFFFF, это есть flat модель памяти. А также ядро работает со страничной адресацией - четырёхуровневой страничной адресацией, эти таблицы в ядре называются глобальный, верхний, средний католог страниц и таблица страниц, на этих страницах реализована между процессами и т.п. - почитай про это

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от MuZHiK-2

Верхние 256 записей в каталоге таблиц страниц отданы под ядро, остальные отдаются под нужды процессов. По этой причине вместо 4 гигов на 32-битной системе ты получишь только 3 гига без ремаппинга.


не по этой причине.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

>не по этой причине.

По какой же тогда причине ?

bengan
()

Эта «разница» достигается за счет какого механизма основанного на регистре CR3.

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

Boy_from_Jungle ★★★★
()

Представь, что используемая память в комьютере побита на куски, скажем, по 4 кб. У каждой программы есть некий список (list), в котором учтены все используемые этой программой куски. Абсолютно все обращения к реальной памяти проходят через сверку доступности данного адреса в списке. Если адрес в списке есть - OK, если нет - генерируется исключение.

Теперь представь, что программе этот список спускается откуда-то сверху. Напрямую модифицировать этот список программа не может, и не использовать его тоже не может. Получается, что хотя физическая память и одна на всех, но, умело составляя списки для процессов, можно избежать коллизий. Процессы будут работать в своём виртуальном адресном пространстве, ничего не зная про АП других процессов и не имея к ним доступа.

Примерно так дело и обстоит в реальности. Трансляция виртуальных адресов в физические и проверка прав делается железом (процессором).

mv ★★★★★
()

На wasm.ru есть цикл статей, в котором хорошо описаны основы работы процессора в защищённом режиме http://www.wasm.ru/publist.php?list=24 еще можно почитать книгу Бовет Д. «Ядро Linux, 3-е издание.»

systemZ
()

В ядре Linux адресные пространства пользователя и ядра «разные». Эта «разница» достигается за счет какого механизма основанного на регистре CR3.

Помимо всего прочего, обрати внимание, что ядро работает в нулевом кольце, а пользовательские программы - в кольце 3. Это часть основного механизма защиты, который идёт аппаратно на >=i386.

man защищённый режим

PS: а cr3 тут ни при чём. это всё уже детали организации страничной адресации

unnamed
()
Ответ на: комментарий от Boy_from_Jungle

>>не по этой причине.

Именно и только по этой. Потому что ядру нужно куда-то маппить девайсы, нужно выделять память под PCI и PCI-E и под другие нужды ввода/вывода и не только, те же видяхи используют часть системной памяти. Даже можем посчитать. В каталоге таблиц страниц 1024 записи, вычитаем 256 и получаем 768 таблиц. В каждой таблице хранится 1024 записи о страницах по 4 Кб каждая (только не суши мне про другой размер страницы, мы рассматривает всеми любимый интел, да и ядро по возможности старается выбирать именно 4 Кб). Итого получаем доступную в юзерспейсе память: 768 * 1024 * 4 = 3145728 Кб памяти, или 3 Гб. Неожиданно, да?

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

В каталоге таблиц страниц 1024 записи, вычитаем 256 и получаем 768 таблиц.

В каждой таблице хранится 1024 записи о страницах по 4 Кб каждая

Ты вообще за какие страницы говоришь?!
При PAE в каждой таблице хранится 512 записи о страницах, и также имеет 32 битовые линейные адреса.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

>>Ты вообще за какие страницы говоришь?!

За обычные, которые в памяти.

При PAE в каждой таблице хранится 512 записи о страницах, и также имеет 32 битовые линейные адреса.

А причем тут PAE? Мы говорим об обычной адресации и о том, почему из 4 Гб на 32-битной машине доступны только 3. Или это типа ты так выкрутиться решил и с потолка начал про PAE нести, о котором в треде вообще не упоминали? Кстати, при PAE под адрес отводится 36 бит, если что. Так по каким причинам вне из 4 Гб доступны только 3, я так и не услышал ответа?

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

Я немного поправлю.

Мы говорим об обычной адресации и о том, почему из 4 Гб на 32-битной машине доступны только 3.

КОНКРЕТНЫЙ ПРОЦЕСС в машине x86 из 4Гб физической памяти в ЮЗЕРСПЕЙСЕ может адресовать максимум 3Гб. А то что ты пишешь не совсем верно.

при PAE под адрес отводится 36 бит

при включенном PAE используются 36 бит ФИЗИЧЕСКОГО адреса. Логические адреса 32-битные как и без PAE.

Chumka ★★★
()
Ответ на: комментарий от MuZHiK-2

За обычные, которые в памяти.

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

А причем тут PAE? Мы говорим об обычной адресации

При PAE по твоему происходит не обычная адресация?!

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от MuZHiK-2

Именно и только по этой. Потому что ядру нужно куда-то маппить девайсы, нужно выделять память под PCI и PCI-E и под другие нужды ввода/вывода и не только, те же видяхи используют часть системной памяти. Даже можем посчитать. В каталоге таблиц страниц 1024 записи, вычитаем 256 и получаем 768 таблиц.


Ты как бы правильно говоришь, но страницы за которые ты говоришь, я так и не понял к чему это?! Как я понял, максимальным количеством физической памяти, с которым может работать ядро, является объем памяти, который мог бы отобразиться в виртуальное адресное пространство ядра минус объем, необходимый для отображения самого ядра.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Chumka

>>КОНКРЕТНЫЙ ПРОЦЕСС в машине x86 из 4Гб физической памяти в ЮЗЕРСПЕЙСЕ может адресовать максимум 3Гб. А то что ты пишешь не совсем верно.

Естественно, я говорю про объем памяти, доступный в юзерспейсе.

при включенном PAE используются 36 бит ФИЗИЧЕСКОГО адреса. Логические адреса 32-битные как и без PAE.

да, при PAE записи в таблице страниц и каталоге таблиц используются 64 битные записи, под адрес отводится 36. Все правильно.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

> Мы говорим об обычной адресации и о том, почему из 4 Гб на 32-битной машине доступны только 3.

4G/4G split реализован уж лет 5 назад.

tailgunner ★★★★★
()
Ответ на: комментарий от Boy_from_Jungle

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

Ты прикидываешься идиотом? Страницы могут быть только одни - те, записи о которых в таблице страниц.

При PAE по твоему происходит не обычная адресация?!

ПАЕ - костыль, опция скажем, так. Я могу собрать ядро и без него. И при ПАЕ записи в таблицах страниц 64 битные, а для 32 битных систем - нет, это не совсем обычная адресация. А если мой проц не поддерживает ПАЕ, то что, линакс не заведется на нем? Обычная адресация это: каталог таблиц стриниц -> таблица страниц -> страница -> физическая память. И записи в таблицах и каталогах 32 битнык.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

>>Ты как бы правильно говоришь, но страницы за которые ты говоришь, я так и не понял к чему это?!

К тому, что часть записей в каталоге таблиц страниц зарезервирована ядром, и поэтому без костыля в виде ПАЕ процесс адресует только до 3 Гб.

Как я понял, максимальным количеством физической памяти, с которым может работать ядро, является объем памяти, который мог бы отобразиться в виртуальное адресное пространство ядра минус объем, необходимый для отображения самого ядра.

Именно.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от mv

>>Х-ню несёшь. Читай книжки.

Может с аргументами где я неправ будет лучше, не? А то я ведь могу аналогично сказать тебе: «х-ню несешь.»

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

> Она сейчас используется в ядре или нет?

Точно не знаю, вроде нет. Да и смысла нет - сейчас 64-битовых процессоров уже в разы больше, чем 32-битовых.

Но реализовано это было, так что насчет «3G - это предел адресного пространства для процесса» - это чушь.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>>Но реализовано это было, так что насчет «3G - это предел адресного пространства для процесса» - это чушь.

Я сейчас почитал статью на LWN про этот патч. Разве его суть не в том, что при больших объемах ОЗУ ядру не хватает 1 Гб на маппинг, остается еще 512 в lowmem, что тоже не ахти. А писать в highmem не есть айс. То есть суть патча в том, что он расширяет пространство для маппинга ядра на больших объемах, или я что-то не так понял? Потому что в статье Молнар рекомендует юзать эту фичу при 64 Гб памяти, для 16 Гб уже не так круто. При меньших объемах может быть оверхед.

MuZHiK-2 ★★★★
()

как все запутано тут ;) но и тема немножко путаная.

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

В ядре Linux адресные пространства пользователя и ядра «разные».


скорее нет, чем да. при входе в ядро контекст не меняется,
те CR3 не переключается.

и вот именно поэтому нам и нужно это разбиение. этот гиг
(при 3/1) _адресного_ пространства нужен ядру не только,
и даже не столько для pci-memory (точнее, для VM_ALLOC).

он нужен для linear mapping на physical memory, те тот
RAM который у нас есть.

поэтому, при 3/1 мы можем использовать только ~ 1G - VMALLOC_TOTAL
RAM, хотя user-space адресное пространство у процессов == 3G.

highmem позволяет утилизовать RAM, который «не виден» через
trivial mapping, это другая история.

4g/4g split - это как раз отказ от общего контекста, iirc.

idle ★★★★★
()
Ответ на: комментарий от idle

скорее нет, чем да. при входе в ядро контекст не меняется,

те CR3 не переключается.

CS и SP меняются.

mv ★★★★★
()
Ответ на: комментарий от mv

> CS и SP меняются.

конечно, нам же нужно повысить уровень привилегий (CPL в cs)

но на трансляцию адресов это никак не влияет, все дескрипторы
имеют одинаковый base/limit.

в контектсе данного обсуждения имеет значение только то, что
из user-space нам недоступен тот самый верхний гиг (kernel
mapping без _PAGE_USER в pte). но mm context тот же самый.

idle ★★★★★
()
Ответ на: комментарий от idle

Я внимательно прочёл вопрос, и увидел, что ТС про кернель/юзерспейс спрашивает, а не про разные юзерские процессы ;)

mv ★★★★★
()
Ответ на: комментарий от mv

браво :) но по сути было интересно прочитать и все выше сказанное, несмотря на то что это уже я смог выяснить, теперь я удостоверился в том что правильно понял это.

Теперь к вопросу

но на трансляцию адресов это никак не влияет, все дескрипторы имеют одинаковый base/limit.

в контектсе данного обсуждения имеет значение только то, что из user-space нам недоступен тот самый верхний гиг (kernel mapping без _PAGE_USER в pte). но mm context тот же самый.

да да да :) вот оно, это я и забыл написать в вопросе )) Юзерские и кернеловские дескрипторы у нас ведь по размеру описываемых адресов одинаковые, эти размеры для линейной памяти. Про то как они в физические пересчитываются не имеет значения. При этом все ядровские адреса начинаються с 0xc0000000. (я все время вот путаю, это линейный или виртуальный адрес).

Отбросим пока страничную память...

У нас есть два дескриптора (USER_DS & KERNEL_DS) описывающие одно и тоже линейное адресное пространство, по идеи неважно в каком из них мы находимся (с точки зрения привилегий) коли оно описывает все доступные адреса то можно обратиться к любому из них к контексте данного дескриптора. Следовательно нет того ограничения привилегий которое по идее предоставляет сегментация, потому что в случае сегментации к произвольному адресу мы могли бы обратиться только через дескриптор описывающий его и тут как раз играл бы роль DPL.

Вспоминаем опят про страницы...

За счет чего достигается то что адресное пространство ядра в виртуальной памяти начинается с 3Gb не смотря на то что дескпритор описывает с 0-4Gb, это происходит за счет какой то там переменной (не помню какая именно, ее через конфиг можно изменить) которая явно выставленна в 3Gb и от нее отплясывает механизм выделения страниц, таким образом что заставляет брать адреса для ядра начиная с 0xc0000000 вроде линейной памяти, и для того чтобы не возникало коллизий тут присутствует механизм с регистром CR3 который при каждом выделение страницы выбирается каким то образом чтобы выделить линейные адреса для очередной страницы какие другие, которые еще не используются (но это по сути важно только для USER_SPCACE и виртуальных адресных пространств процессов(за счет этого CR3 достигается что каждый процесс работает с 0x00000000 (непомню какго точно значения))).

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

Cupper
() автор топика
Ответ на: комментарий от Cupper

> За счет чего достигается то что адресное пространство ядра в

виртуальной памяти начинается с 3Gb не смотря на то что дескпритор

описывает с 0-4Gb



да оно и не начинается. что для ядра, что для user-space,
адресное пространство это 0-4GB.

просто мы «мапим» физическую память начиная с PAGE_OFFSET,
это, в сущности, и есть наше разбиение.

но! в этом trivial mapping _PAGE_USER (кажется, он называется
supervisor bit) в pte не ставится. поэтому доступ к этим
страницам требует CPL == 0.

(остальные вопросы в этом параграфе не понял)

из за чего же все таки из юзерспейса нельзя получить доступ к

данным ядра, но то что не из за DPL это уже блин однозначно.



see above про CPL/_PAGE_USER.

те, ограничение происходит из-за hardware hardware, а не потому,
что контекст разный.

idle ★★★★★
()
Ответ на: комментарий от idle

> но! в этом trivial mapping _PAGE_USER (кажется, он называется

supervisor bit) в pte не ставится. поэтому доступ к этим

страницам требует CPL == 0.



точнее, доступ к страницам по этим виртуальным адресам. сами
эти страницы могут быть видны и по другому адресу.

idle ★★★★★
()
Ответ на: комментарий от idle

вот влзьмем за основу то что вы сказали и попробуем рассмотреть такой безумный случай:

выполняемся мы значит в ядре, и делаем такой безумный финт ушами и с помощью iret понижаем себе привилегии (изменяем селкторы в CS, SS, DS) до юзерских, при это оставаясь в адресном пространстве ядра. Теперь грубо говоря мы выполняемся на 3 кольце, соответственно часть ассемблерных привилегированных инструкций нам уже не доступно из за проверки CPL из регистра cs и также нам недоступны некоторые функция ядра юзающие эти инструкции и что то там еще. Вот как бы включается хардваре защита. НО, нам не что не мешает писать в память ядра, так как обращение к нему идет в обход всяких там селекторов и дескрипторов. Грубо гворя мы можемь изменить значение esp на какое хотим и с помощью пушей «наложить» туда чего хотим.

При выше описанных условиях мы можем не взерая на DPL писать в ядрому память, так как мы знаем ее адреса и обращаемся к ней на прямую. Теперь вернемся в адекватность, в пространство пользователя, где у нас CS, SS, DS имеют опять таки селекторы 3 кольца, но вот в этом случае хрена с два мы можешь писать в ядро. И не можем почему ? потому что мы не знаем «адресов» или еще чего ?

Cupper
() автор топика
Ответ на: комментарий от Cupper

не пойму, что непонятно. и вопросов не понимаю.

так как обращение к нему идет в обход всяких там селекторов

и дескрипторов.



как это?

мы знаем ее адреса и обращаемся к ней на прямую


тоже не понял. а «не-напрямую», это что?

И не можем почему ? потому что мы не знаем «адресов» или

еще чего ?



да почему же не знаем? в который раз, адресное п-во
одно и адрес один и тот же.

вот программа делает ptr = mmap(PROT_NONE) и ничего в
*ptr сделать не может. это же не потому, что «адресов»
не знает? нет конечно, это потому, что в pte должны
быть выставлены нужные биты.

что касается ядра, я дважды писал про _PAGE_USER bit
в pte, при его отсутствии нужен CPL == 0.

idle ★★★★★
()

просьба по LORWIKI

поправьте пожалуйста статью http://www.linux.org.ru/wiki/en/32_%D0%B8%D0%BB%D0%B8_64_%D0%B1%D0%B8%D1%82%D...

( 32 vs 64 )

32 битная система + 64 битное ядро

Минусы


* Невозможность адресации более 3 гигабайт памяти одним 32-битным процессом



сколько все-таки памяти может адресовать 32 битный процесс на 64 бит ядре , с учетом того что есть personalities
ADDR_LIMIT_32BIT = 2 GB и ADDR_LIMIT_3GB = 3GB ?


Sylvia ★★★★★
()
Ответ на: просьба по LORWIKI от Sylvia

боюсь соврать, никогда с этим не сталкивался.

на первый взгляд:

- ADDR_LIMIT_32BIT это вообще не для x86. разные
архитекуры его как-то по разному интерпретируют.
flat binaries его ставят, но это для !MMU, те
опять-таки !x86.

- ADDR_LIMIT_3GB. ох, не уверен, что я правильно
понимаю то, что мне показывает grep. если коротко,
32-bit application под 64-bit kernel может иметь
почти 4G в address space, но это может поломать
какие-то приложения, которые к этому не готовы.
поэтому ADDR_LIMIT_3GB понижает TASK_SIZE до 3G.
см TASK_SIZE в arch/x86/include/asm/processor.h

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.