6.5.1. Процессы и программа управления памятью
Работа, связанная с памятью, производимая посредством fork():
Выделение памяти
- 1 страница для task_struct.
- 1 страница для стека ядра.
- 1 для pg_dir и несколько для pg_tables (co[py_page_tables)
Другие изменения
- ss0 установить на адрес сегмента стека ядра (0х10) чтобы быть уверенным?
- esp0 установит на вершину вновь созданного kernel_stack_page
- cr3 устанавливается посредством copy_page_tables() для указания на вновь размещенную директорию страниц.
- ltd=_LTD(task_nr) создает новый дескриптор ltd.
- дескриптор устанавливается в gdt для нового tss и ltd[].
- Остальные регистры наследуются от родителя.
Процессы прекращают разделение их сегментов данных и кода (хотя они имеют раздельные локальные таблицы дескрипторов, входы указывают на те же сегменты). Страницы стека и данных будут скопированы, когда родитель или наследник будет писать в них (СOPY-ON-WRITE)
Работа, связанная с памятью, производимая посредством exec():
- Выделение памяти
- 1 страница для exec-заголовка полного файла для omagic
- 1 страница или больше для стека (MAX_ARG_PAGES)
- clear_page_tables() используется для удаления старых страниц.
- change_ltd() устанавливает дескрипторы в новом LTD[]
- ltd[1] = code base = 0x00, limit = TASK_SIZE
- ltd[2] = data base = 0x00, limit = TASK_SIZE
Эти сегменты представляются DPL=3,P=1,S=1,G=1 type=a(code) или 2(data)
- До MAX_ARG_PAGES грязные страницы argv и envp размещаются и сохраняются на вершине сегмента данных для вновь созданного пользовательского стека.
- Установить указатель инструкции вызывающей программы eip = ex.a_entry.
- Установить указатель стека вызывающей программы на созданный стек (esp = stack pointer) Данные будут выбраны из стека при возобновлении вызывающей программы.
- Редактирование ограничений на память
end_coe = ex.a_text
end_data = end_code + ex.a_data
brk = end_data + ex.a_bss
Программные и аппаратные прерывания управляются внутри контекста текущей задачи. Более детально, директория страниц текущего процесса используется при трансляции адреса. Сегменты, однако, являются сегментами ядра и таким образом все линейные адреса указывают в область памяти ядра. Предположим, например, что пользовательский процесс выполняет системный вызов и ядро хочет получить доступ к переменной по адресу 0х01. Линейный адрес будет равен 0хс0000001 (использование сегментов ядра) и физический адрес - 0х01. Буква здесь присутствует вследствие того, что директория страниц процесса отображает этот диапазон точно как page_pg_dir.
Область ядра (0хс0000000 + high_memory) отображается через таблицы страниц ядра, которые являются частью RESURVED памяти. Поэтому они разделяются всеми процессами. Во время распараллеливания copy_page_tables() напрямую обращается к таблицам RESERVED страниц. Она устанавливает указатели в директориях страниц процесса, чтобы указывать на таблицы страниц ядра и не размещает в памяти новых таблиц страниц, как это обычно делается. В качестве примера kernel_stack_page (который размещен где-то в области ядра) не нуждается в связанной page_table, размещенной в p_dir процесса, чтобы отобразить ее.
Инструкция прерывания устанавливает указатель стека и сегмент стека из привилегированных 0 значений, сохраненных в tss текущей задачи. Заметьте, что стек ядра в действительности является фрагментированным объектом - это не единственный объект, а группа стековых фреймов, каждый из которых размещается в памяти при создании процесса и освобождает память при окончании его. Стек ядра никогда не должен расти внутри контекста процесса слишком быстро, чтобы не расширится за пределы текущего фрейма.
[ Назад | Оглавление | Далее ]
|