Почему любую программу перед выполнением нужно загрузить в оперативную память
1. Зачем в компьютере нужна память?
2. С какой целью память делится на внутреннюю и внешнюю?
3. Верно ли, что внешняя память располагается вне корпуса компьютера? Приведите примеры.
4. Назовите все виды компьютерной памяти, которые вы знаете. Зачем они используются? Какими свойствами обладают?
5. К каким видам памяти применим принцип адресности фон Неймана?
6. Что означает термин «произвольный доступ к памяти»?
7. Зачем нужно ПЗУ в компьютере? Можно ли при необходимости изменить его содержимое на домашнем компьютере?
8. Что такое носитель информации? Какие носители вы можете назвать?
9. Какими носителями внешней памяти вы пользовались? Каков их объём и какую примерно его часть вы использовали?
10. Перечислите все известные вам виды дисков.
11. Что такое сектор диска?
12. Можно ли считать с диска отдельно взятый байт? Как его всё-таки получить?
13. Какую роль играет контроллер при считывании данных с диска?
14. Почему любую программу перед выполнением требуется загрузить в оперативную память?
15. Что такое флэш-память и в каких запоминающих устройствах она используется?
16. Какие разновидности полупроводникового ОЗУ существуют? Что служит в них запоминающим элементом? Каковы свойства названных вами типов ОЗУ?
17. Для чего создана кэш-память, как она работает и как повышает производительность компьютера?
18. Может ли программа обращаться к ячейкам кэш-памяти? Подумайте, относится ли кэш-память к архитектуре компьютера. Почему?
*19. Почему кэш называют ассоциативной памятью? Сравните с человеческой памятью, которую тоже часто называют ассоциативной.
20. Кэширование — это аппаратный или программный приём? Приведите примеры.
21. Перечислите все известные вам уровни иерархии компьютерной памяти и кратко охарактеризуйте их. Как меняются объём и быстродействие памяти при переходе на другой уровень иерархии (вверх или вниз)?
22. Почему компьютерам требуются все большие объёмы памяти?
23. Как работает механизм виртуальной памяти?
*24. Чем ограничен объём виртуальной памяти?
25. Какие основные характеристики используются для памяти? В каких единицах они измеряются?
26. Какая характеристика используется только для внешней памяти?
а) «Устройства памяти разных поколений компьютеров»
б) «Кэш-память в современных процессорах»
в) «Виртуальная память»
г) «Что такое BIOS?»
Следующая страница Задачи
Cкачать материалы урока
После включения компьютера в его оперативной памяти нет операционной системы. Само по себе, без операционной системы, аппаратное обеспечение компьютера не может выполнять сложные действия, такие как, например, загрузку программы в память. Таким образом мы сталкиваемся с парадоксом, который кажется неразрешимым: для того, чтобы загрузить операционную систему в память, мы уже должны иметь операционную систему в памяти.
Решением данного парадокса является использование специальной маленькой компьютерной программы, называемой начальным загрузчиком, или BIOS (Basic Input/Output System). Эта программа не обладает всей функциональностью операционной системы, но её достаточно для того, чтобы загрузить другую программу, которая будет загружать операционную систему. Часто используется многоуровневая загрузка, в которой несколько небольших программ вызывают друг друга до тех пор, пока одна из них не загрузит операционную систему.
В современных компьютерах процесс начальной загрузки начинается с выполнения процессором команд, расположенных в постоянной памяти (например на IBM PC — команд BIOS), начиная с предопределённого адреса (процессор делает это после перезагрузки без какой бы то ни было помощи) . Данное программное обеспечение может обнаруживать устройства, подходящие для загрузки, и загружать со специального раздела выбранного устройства (чаще всего загрузочного сектора данного устройства) загрузчик ОС.
Начальные загрузчики должны соответствовать специфическим ограничениям, особенно это касается объёма. Например, на IBM PC загрузчик первого уровня должен помещаться в первых 446 байтах главной загрузочной записи, оставив место для 64 байт таблицы разделов и 2 байта для сигнатуры AA55, необходимой для того, чтобы BIOS выявил сам начальный загрузчик.
Данный пример основан на начальном загрузчике одного из миникомпьютеров, выпущенного в 1970-х годах фирмой Nicolet Instrument Corporation.
0: записать в регистр P число 106
1: проверить что устройство считывания с перфолент может начинать считывание
2: если не может, перейти к п. 1
3: прочитать байт с устройства считывания с перфолент и записать его в аккумулятор
4: если перфолента закончилась, перейти к п. 8
5: записать значение, хранимое в аккумуляторе, в оперативную память по адресу, хранящемуся в регистре P
6: уменьшить значение регистра P на единицу
7: перейти к п. 1
Управление памятью – одна из главных задач ОС. Она критична как для программирования, так и для системного администрирования. Я постараюсь объяснить, как ОС работает с памятью. Концепции будут общего характера, а примеры я возьму из Linux и Windows на 32-bit x86. Сначала я опишу, как программы располагаются в памяти.
Каждый процесс в многозадачной ОС работает в своей «песочнице» в памяти. Это виртуальное адресное пространство, которое в 32-битном режиме представляет собою 4Гб блок адресов. Эти виртуальные адреса ставятся в соответствие (mapping) физической памяти таблицами страниц, которые поддерживает ядро ОС. У каждого процесса есть свой набор таблиц. Но если мы начинаем использовать виртуальную адресацию, приходится использовать её для всех программ, работающих на компьютере – включая и само ядро. Поэтому часть пространства виртуальных адресов необходимо резервировать под ядро.
Это не значит, что ядро использует так много физической памяти – просто у него в распоряжении находится часть адресного пространства, которое можно поставить в соответствие необходимому количеству физической памяти. Пространство памяти для ядра отмечено в таблицах страниц как эксклюзивно используемое привилегированным кодом, поэтому если какая-то программа пытается получить в него доступ, случается page fault. В Linux пространство памяти для ядра присутствует постоянно, и ставит в соответствие одну и ту же часть физической памяти у всех процессов. Код ядра и данные всегда имеют адреса, и готовы обрабатывать прерывания и системные вызовы в любой момент. Для пользовательских программ, напротив, соответствие виртуальных адресов реальной памяти меняется, когда происходит переключение процессов:
Голубым отмечены виртуальные адреса, соответствующие физической памяти. Белым – пространство, которому не назначены адреса. В нашем примере Firefox использует гораздо больше места в виртуальной памяти из-за своей легендарной прожорливости. Полоски в адресном пространстве соответствуют сегментам памяти таким, как куча, стек и проч. Эти сегменты – всего лишь интервалы адресов памяти, и не имеют ничего общего с сегментами от Intel. Вот стандартная схема сегментов у процесса под Linux:
Когда программирование было белым и пушистым, начальные виртуальные адреса сегментов были одинаковыми для всех процессов. Это позволяло легко удалённо эксплуатировать уязвимости в безопасности. Зловредной программе часто необходимо обращаться к памяти по абсолютным адресам – адресу стека, адресу библиотечной функции, и т.п. Удаленные атаки приходилось делать вслепую, рассчитывая на то, что все адресные пространства остаются на постоянных адресах. В связи с этим получила популярность система выбора случайных адресов. Linux делает случайными стек, сегмент отображения в память и кучу, добавляя смещения к их начальным адресам. К сожалению, в 32-битном адресном пространстве особо не развернёшься, и для назначения случайных адресов остаётся мало места, что делает эту систему не слишком эффективной.
Самый верхний сегмент в адресном пространстве процесса – это стек, в большинстве языков хранящий локальные переменные и аргументы функций. Вызов метода или функции добавляет новый кадр стека (stack frame) к существующему стеку. После возврата из функции кадр уничтожается. Эта простая схема приводит к тому, что для отслеживания содержимого стека не требуется никакой сложной структуры – достаточно всего лишь указателя на начало стека. Добавление и удаление данных становится простым и однозначным процессом. Постоянное повторное использование районов памяти для стека приводит к кэшированию этих частей в CPU, что добавляет скорости. Каждый поток выполнения (thread) в процессе получает свой собственный стек.
Можно прийти к такой ситуации, в которой память, отведённая под стек, заканчивается. Это приводит к ошибке page fault, которая в Linux обрабатывается функцией expand_stack(), которая, в свою очередь, вызывает acct_stack_growth(), чтобы проверить, можно ли ещё нарастить стек. Если его размер не превышает RLIMIT_STACK (обычно это 8 Мб), то стек увеличивается и программа продолжает исполнение, как ни в чём не бывало. Но если максимальный размер стека достигнут, мы получаем переполнение стека (stack overflow) и программе приходит ошибка Segmentation Fault (ошибка сегментации). При этом стек умеет только увеличиваться – подобно государственному бюджету, он не уменьшается обратно.
Динамический рост стека – единственная ситуация, в которой может осуществляться доступ к свободной памяти, которая показана белым на схеме. Все другие попытки доступа к этой памяти вызывают ошибку page fault, приводящую к Segmentation Fault. А некоторые занятые области памяти служат только для чтения, поэтому попытки записи в эти области также приводят к Segmentation Fault.
После стека идёт сегмент отображения в память. Тут ядро размещает содержимое файлов напрямую в памяти. Любое приложение может запросить сделать это через системный вызов mmap() в Linux или CreateFileMapping() / MapViewOfFile() в Windows. Это удобный и быстрый способ организации операций ввода и вывода в файлы, поэтому он используется для подгрузки динамических библиотек. Также возможно создать анонимное место в памяти, не связанное с файлами, которое будет использоваться для данных программы. Если вы сделаете в Linux запрос на большой объём памяти через malloc(), библиотека C создаст такую анонимное отображение вместо использования памяти из кучи. Под «большим» подразумевается объём больший, чем MMAP_THRESHOLD (128 kB по умолчанию, он настраивается через mallopt().)
Если в куче оказывается недостаточно места для выполнения запроса, эту проблему может обработать сама программа без вмешательства ядра. В ином случае куча увеличивается системным вызовом brk(). Управление кучей – дело сложное, оно требует хитроумных алгоритмов, которые стремятся работать быстро и эффективно, чтобы угодить хаотичному методу размещению данных, которым пользуется программа. Время на обработку запроса к куче может варьироваться в широких пределах. В системах реального времени есть специальные инструменты для работы с ней. Кучи тоже бывают фрагментированными:
И вот мы добрались до самой нижней части схемы – BSS, данные и текст программы. BSS и данные хранят статичные (глобальные) переменные в С. Разница в том, что BSS хранит содержимое непроинициализированных статичных переменных, чьи значения не были заданы программистом. Кроме этого, область BSS анонимна, она не соответствует никакому файлу. Если вы пишете static int cntActiveUsers , то содержимое cntActiveUsers живёт в BSS.
Сегмент данных, наоборот, содержит те переменные, которые были проинициализированы в коде. Эта часть памяти соответствует бинарному образу программы, содержащему начальные статические значения, заданные в коде. Если вы пишете static int cntWorkerBees = 10 , то содержимое cntWorkerBees живёт в сегменте данных, и начинает свою жизнь как 10. Но, хотя сегмент данных соответствует файлу программы, это приватное отображение в память (private memory mapping) – а это значит, что обновления памяти не отражаются в соответствующем файле. Иначе изменения значения переменных отражались бы в файле, хранящемся на диске.
Пример данных на диаграмме будет немного сложнее, поскольку он использует указатель. В этом случае содержимое указателя, 4-байтный адрес памяти, живёт в сегменте данных. А строка, на которую он показывает, живёт в сегменте текста, который предназначен только для чтения. Там хранится весь код и разные другие детали, включая строковые литералы. Также он хранит ваш бинарник в памяти. Попытки записи в этот сегмент оканчиваются ошибкой Segmentation Fault. Это предотвращает ошибки, связанные с указателями (хотя не так эффективно, как если бы вы вообще не использовали язык С). На диаграмме показаны эти сегменты и примеры переменных:
Изучить области памяти Linux-процесса можно, прочитав файл /proc/pid_of_process/maps. Учтите, что один сегмент может содержать много областей. К примеру, у каждого файла, сдублированного в память, есть своя область в сегменте mmap, а у динамических библиотек – дополнительные области, напоминающие BSS и данные. Кстати, иногда, когда люди говорят «сегмент данных», они имеют в виду данные + bss + кучу.
Бинарные образы можно изучать при помощи команд nm и objdump – вы увидите символы, их адреса, сегменты, и т.п. Схема виртуальных адресов, описанная в этой статье – это т.н. «гибкая» схема, которая по умолчанию используется уже несколько лет. Она подразумевает, что переменной RLIMIT_STACK присвоено какое-то значение. В противном случае Linux использует «классическую» схему:
1. Два процессора имеют одинаковую тактовую частоту. Всегда ли это означает, что у них одинаковое быстродействие?
2. Оцените, сколько миллиардов простых операций может выполнить за одну минуту процессор с тактовой частотой 1 ГГц.
3. Сравните оперативную и долговременную память, ответив на вопросы.
— Когда данные хранятся в оперативной памяти, а когда — в долговременной?
— Какой вид памяти имеет больший объём?
— Что происходит с данными при выключении компьютера?
4. Почему в компьютерах нельзя обойтись одним видом памяти — оперативной или долговременной?
5. Почему любую программу перед выполнением нужно загрузить в оперативную память?
6. Придумайте примеры данных, которые не нужно хранить в облачном хранилище. Поясните почему.
7. Какие проблемы могут возникнуть, если в компьютере нет ПЗУ?
8. Что такое адрес ячейки памяти?
9. Почему обмен данными между устройствами компьютера с помощью шины оказался наилучшим решением?
10. В чём заключается принцип открытой архитектуры?
11. Почему обмен данными осложнится, если из схемы на рис. 2.5 удалить контроллеры?
12. Что такое носитель данных? Какие носители вы можете назвать?
13. Какими устройствами внешней памяти вы пользовались? Каков их объём и какую примерно его часть вы использовали?
14. В группах по 3-4 человека предложите и затем обсудите в классе, какие команды вы бы предложили включить в список команд процессора.
15. Выполните по указанию учителя задания в рабочей тетради.
а) «История развития микропроцессоров»
б) «Зачем нужно ПЗУ?»
в) «История развития долговременной памяти»
г) «Облачные хранилища данных — "за" и "против"»
Интересные сайты
Следующая страница Процессор
Cкачать материалы урока
1. Зачем в компьютере нужна память?
2. С какой целью память делится на внутреннюю и внешнюю?
3. Верно ли, что внешняя память располагается вне корпуса компьютера? Приведите примеры.
4. Назовите все виды компьютерной памяти, которые вы знаете. Зачем они используются? Какими свойствами обладают?
5. К каким видам памяти применим принцип адресности фон Неймана?
6. Что означает термин «произвольный доступ к памяти»?
7. Зачем нужно ПЗУ в компьютере? Можно ли при необходимости изменить его содержимое на домашнем компьютере?
8. Что такое носитель информации? Какие носители вы можете назвать?
9. Какими носителями внешней памяти вы пользовались? Каков их объём и какую примерно его часть вы использовали?
10. Перечислите все известные вам виды дисков.
11. Что такое сектор диска?
12. Можно ли считать с диска отдельно взятый байт? Как его всё-таки получить?
13. Какую роль играет контроллер при считывании данных с диска?
14. Почему любую программу перед выполнением требуется загрузить в оперативную память?
15. Что такое флэш-память и в каких запоминающих устройствах она используется?
16. Какие разновидности полупроводникового ОЗУ существуют? Что служит в них запоминающим элементом? Каковы свойства названных вами типов ОЗУ?
17. Для чего создана кэш-память, как она работает и как повышает производительность компьютера?
18. Может ли программа обращаться к ячейкам кэш-памяти? Подумайте, относится ли кэш-память к архитектуре компьютера. Почему?
*19. Почему кэш называют ассоциативной памятью? Сравните с человеческой памятью, которую тоже часто называют ассоциативной.
20. Кэширование — это аппаратный или программный приём? Приведите примеры.
21. Перечислите все известные вам уровни иерархии компьютерной памяти и кратко охарактеризуйте их. Как меняются объём и быстродействие памяти при переходе на другой уровень иерархии (вверх или вниз)?
22. Почему компьютерам требуются все большие объёмы памяти?
23. Как работает механизм виртуальной памяти?
*24. Чем ограничен объём виртуальной памяти?
25. Какие основные характеристики используются для памяти? В каких единицах они измеряются?
26. Какая характеристика используется только для внешней памяти?
а) «Устройства памяти разных поколений компьютеров»
б) «Кэш-память в современных процессорах»
в) «Виртуальная память»
г) «Что такое BIOS?»
Следующая страница Задачи
Cкачать материалы урока
Читайте также: