Ядро ОС Linux

       

Инициализация памяти


В start_kernel (main.c) имеются 3 переменные, связанные с инициализацией памяти:

  • memory_start начинается от 1MB. Изменяется посредством инициализации устройства.
  • memory_end конец физической памяти: 8MB, 16MB и т.д.
  • low_memory_start конец кода и данных ядра, загружаемых первоначально.
  • Каждое устройство при инициализации по-своему берет memory_stsrt и возвращает измененное значение, если оно выделяет пространство начиная с memory_stsrt (просто захватывая его). paging_init() инициализирует таблицы страниц в swapper_pg_dir (начинающиеся с 0хс0000000), чтобы накрыть всю физическую память начиная с memory_start и кончая memory_end. В действительности первые 4МВ обрабатываются в startup_32 (head.s). memory_start увеличивается, если добавляется какая-либо новая page_tables. При пребывании по обращению по пустому указателю в ядре первая страница обнуляется.

    В shed_init() ltd и tss дескрипторы задачи task[0] устанавливаются в GDT, и загружаются в TR и DTR (единственный случай, когда это делается явно). TRAP GATE (0х80) устанавливается для system_call(). Флаг вложенной задачи сбрасывается при подготовке к переходу в пользовательский режим. Таймер включается. task_struct для task[0] в полном объеме появляется в .

    Далее с помощью mem_init() создается mem_map, чтобы отражать текущее использование физических страниц. Это состояние, которое отражается в карте физической памяти, описанной в предыдущем разделе.

    Linux переходит в пользовательский режим посредством iret после сохранения в стеке ss, esp и т.п. Естественно, что сегменты пользователя для task[0] управляются прямо через сегменты ядра, т.о. выполнение продолжается точно с того места, где оно было прервано.

    task[0]:

  • pg_dir = swapper_pg_dir, что означает, что управление адресами происходит только в области от 3GB до 3GB + high_memory/
  • LTD[1] = код пользователя, base=0xc0000000, size=640K
  • LTD[2] = данные пользователя, base=0xc0000000, size=640K
  • Первый вызов exec() устанавливает входы LTD для task[1] в пользовательские значения с base=0x0, limit= TASK_SIZE = 0xc0000000. Согласно этому ни один процесс не видит сегменты ядра пока находится в пользовательском режиме.



    Содержание раздела