Открытая память
Самый простой вариант управления памятью — отсутствие диспетчера памяти
и возможность загружать в системе только один процесс. Именно так работают
СР/М и RT-ll SJ (Single-Job, однозадачная). В этих системах программы
загружаются с фиксированного адреса PROG_START.
В СР/М это ОхЮО; в RT-ll — 01000. По адресам от 0 до начала программы
находятся векторы прерываний, а в RT-11 — также и стек программы. Операционная
система размещается в старших адресах памяти. Адрес SYS_START,
с которого она начинается, зависит от количества памяти у машины и от
конфигурации ОС (рис. 4.1).
Рис. 4.1. Управление памятью в однопроцессной ОС с открытой
памятью
В этом случае управление памятью со стороны системы состоит в том, что
загрузчик проверяет, поместится ли загружаемый модуль в пространство от
PROG_START до
SYS_START. Если объем памяти, который использует программа, не
будет меняться во время ее исполнения, то на этом все управление и заканчивается.
Однако программа может использовать динамическое управление памятью, например
функцию malloco или что-то в этом роде. В этом случае уже код maiioco
должен следить за тем, чтобы не залезть в системные адреса. Как правило,
динамическая память начинает размещаться с адреса PROG_END
= PROG_START + PROG_SIZE. FROG_SIZE в данном случае обозначает
полный размер программы, т. е. размер ее кода, статических данных и области,
выделенной под стек.
Функция malloc () поддерживает некоторую структуру
данных, следящую за тем, какие блоки памяти из уже выделенных были освобождены.
При каждом новом запросе она сначала ищет блок подходящего размера в своей
структуре данных и, только когда этот поиск завершится неудачей, просит
новый участок памяти у системы. Для этого используется переменная, которая
в библиотеке языка С называется brk_addr (рис.
4.2, пример 4.1).
Рис. 4.2. Загруженная программа и brk_addr
Изначально эта переменная равна PROG_END,
ее значение увеличивается при выделении новых блоков, но в некоторых случаях
может и уменьшаться. Это происходит, когда программа освобождает блок,
который заканчивается а текущем значении brkievei.
Пример 4.1. Выделение дополнительной памяти в GNU
LibC для Linux
morecore.с:
/* Copyright (С) 1991, 1992 Free Software Foundation, Inc.
Этот файл является частью библиотеки С проекта GNU (GNU С Library).
GNU С Library является свободным программным обеспечением;
вы можете передавать ее и/или модифицировать ее в соответствии
с положениями GNU General Public License версии 2 или (по вашему выбору)
'
любой более поздней версии.
Библиотека GNU С распространяется в надежде, что она будет полезна, но
БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без неявно предполагаемых гарантий
КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. Подробнее см.
GNU General Public License.
Вы должны были получить копию GNU General Public License вместе с
GNU С Library; см. файл COPYING. Если вы ее не получили, напишите по
адресу: Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
tifndef _MALLOC_INTERNAL tfdefine _MALLOC_INTERNAL tinclude <malloc.h>
#include <stdlib.h> ttinclude <stdio.h>
#include <errno.h> tinclude <sys/syscall.h> tendif
#ifndef _GNU_LIBRARY_
tfdefine __sbrk sbrk
#endif
extern void * ___brk_addr;
extern ptr t sbrk P ((int increment));
int _ initbrk Р ( (void) ) ;
fifndef NULL fdefine NULL 0 fendif
/* Выделить еще INCREMENT байтов пространства данных
и возвратить начало пространства данных или NULL при ошибках. Если INCREMENT
отрицателен, сжать пространство данных. */
__ptr_t
default_morecore (ptrdiff_t increment)
{
ptr_t result = _ sbrk ((int) increment);
if (result == ( _ ptr_t) -1)
return NULL; return result;
/* Эта функция почти полностью аналогична _ def ault_morecore ( ) * Но
она вызывается только однажды через morecore.
*/
_ ptr_t
_ default_morecore_init (ptrdiff_t increment)
{
_ ptr_t result;
if ( _ init_brk() != 0)
return NULL;
if ( _ morecore == _ default_morecore_init)
_mprecore = _ default_morecore;
result = _ sbrk ((int) increment);
if (result == ( _ ptr_t) -1)
return NULL;
return result;
}
|