Pull to refresh

Comments 12

Хороший пост, спасибо.

Единственное — не совсем понятно — что хранится в Kernel Space — код системных функций непосредственно отображается в виртуальное адресное пространство каждого процесса?
Спасибо. Мне очень нравятся и другие статьи Gustavo Duarte — посмотрите, если будет время. На данный момент я понимаю это имено так — код ядра, код системных вызовов, драйвера должны быть там. Но это — общий взгляд на вещи. В деталях может оказаться сложней.
Да, правда в Page Table стоит флаг System, который говорит процессору о том, что доступ к страницам Kernel Space доступен только с ring 0, так что ничего опасного в этом нет.
Ну по идее да, там должен быть код ядра, но его, чисто теоретически, можно и в нижние 3Гб упихать, там ничего секретного нет. Что важнее, там всякие таблички для процесса: маппинг дескрипторов файловых и прочей ерунды. На винде вроде бы из за их потенциальных размеров они даже не сразу их в 1Гб научились упихивать.
Если в Linux запросить выделение большого блока памяти с помощью malloc(), то вместо того, чтобы выделить память в куче, стандартная библиотека C задействует механизм анонимного отображения. Слово «большой», в данном случае, означает величину в байтах большую, чем значение константы MMAP_THRESHOLD. По умолчанию, это величина равна 128 кБ, и может контролироваться через вызов mallopt().

Столкнулся с несколько другим поведением. Программа выделяла много памяти блоками по несколько мегабайт. В процессер работы, если блок становился маловат он удалялся, а вместо него выделялся чуть большего размера. В windows все работало как надо, а в ubuntu конце концов заканчивалась вся оперативная память (все 32 гигабайта). Дело было в фрагментации адресного пространства и в том что системе не возвращаются «свободные» сегменты адресов, они остаются замапленными на физическую память. Переделал выделение памяти на анонимный mmap, тогда все нормализовалось.
Интересный момент. Нужно будет поэкспериментировать.
А можно по подробнее, где в каком случае в столкнулись с таким поведением? Это какой-то нестандартный realloc?
Забыли добавить, что такое BSS, видящим это впервые может быть не ясно. BSS, Block Started by Symbol. В образе бинарника в BSS записывается только число и кол-во переменных, которое должно быть им инициализировано — к примеру 10 интов со значением 0. Когда программа загружается в память, то уже в ней будет зарезервировано 10 нулей.
Да, спасибо за дополнение.
Добрый вечер! Спасибо за отличную статью! Я новичек в kernel и меня уже второй день мучает вопрос, который я никак нигде не могу нагуглить. На сколько я понял, отображение файла — это чтение данных из него через адрес в виртуальной памяти, без непосредственной загрузки данных в память (только в кэш, а он маленький совсем). То есть, при попытке считать по адресу замэпленного файла, на самом деле происходит чтение из файла.
Вы писали, что в Линуксовском процессе все so-шки и файл с кодом программы мапятся в память как раз по описанному механизму. Правильно ли я понимаю, что при чтении инструкции из so-шной библиотеки или кода, каждый (ну или почти каждый) раз идет обращение к файлу (через отображение), то есть к ПЗУ, то есть к жесткому диску, то есть ОЧЕНЬ МЕДЛЕНО. Как-то странно получается, ведь оперативная память на то и сделана, чтобы уменьшить колличество чтений из ПЗУ и ускорить выполнение… Или эта so-шка в начале вся грузится в память (хотя смысл тогда в отображении)… не понимаю… Буду очень признателен за ответ на вопрос)
Пршу прощение за беспокойство — нашел ответ на свой вопрос в статье «Page-кэш, или как связаны между собой оперативная память и файлы».
Здравствуйте. Рад, что материал оказался Вам полезен.
Sign up to leave a comment.