Flags
Означает тип требуемой памяти. Эти флаги передаются в систему близнецов для изменения поведения kmalloc (). Табл. 4.6 демонстрирует флаги, которые подробно описаны в подразделе «Система близнецов».
Строки 2102-2104
Поиск первого кеша с объектами больше требуемого размера.
Строки 2112-2113
Выделение объекта из зоны памяти, указанной в параметре flags.
4.6.2 kmem_cache_alloc()
Это функция-обертка для____ cache_alloc (). Она не обладает никакой дополнительной
функциональностью, а только передает параметры:
ram/slab.с
2070 void * kmem_cache_alloc (kmem_cache_t *cachep, int flags) 2071 {
2072 return__ cache_alloc(cachep, flags);
2073 }
Cachep
Параметр cachep - это описатель кеша, из которого мы хотим выделить объект.
Flags
Тип требуемой памяти. Передаются прямо, как указано в kmalloc ().
Для того чтобы освободить память байтового размера, выделенную с помощью kmalloc (), ядро предоставляет интерфейс kf гее (), получающую в качестве параметра указатель на память, возвращаемый kmalloc (). Рис. 4.9 демонстрирует передачу управления от kf гее к kmem_f reepages.
Структуры памяти процесса в Linux
kfree() | ___ cacheJreeQ | kmem_freepages() | ||||
Рис. 4.9. Граф вызова kfree
Структуры памяти процесса в Linux
До сих пор мы описывали, как ядро распоряжается собственной памятью. Теперь мы обратим наше внимание на программы пользовательского пространства и на то, как ядро управляет памятью программ. Чудеса виртуальной памяти позволяют процессам пользовательского пространства работать с такой же эффективностью, как если бы им была доступна вся память. В реальности ядро управляет тем, что следует загрузить, как это загружать и что делать с загруженным дальше. Все, о чем мы рассуждали до сих пор в этой главе, связано с тем, как ядро управляет памятью и обеспечивает полную прозрачность для программ пользовательского пространства.
Во время создания процесса пользовательского пространства ему назначается виртуальное адресное пространство. Как говорилось ранее, виртуальное адресное пространство процесса представляет собой диапазон ^сегментированных линейных адресов, которые может использовать процесс. Размер диапазона определяется размером регистров системной архитектуры. Большинство систем обладает 32-битовым адресным пространством, с другой стороны, существуют системы, например G5, которые обладают 64-битовым адресным пространством.
Во время создания диапазон адресов процесса может расширяться или сужаться с помощью добавляемых или убираемых интервалов адресов (address intervals) соответственно. Интервал адресов (диапазон адресов) не определяется до тех пор, пока не будет вызван регион памяти (memory region)или область памяти (memory area).Это полезно при разделении диапазона адресов процесса на несколько зон разных типов. Эти разные типы обладают собственными схемами защиты или характеристиками. Схемы защиты памяти процесса связаны с контекстом процесса. Например, некоторые части программного кода помечаются как доступные только для чтения (текст), тогда как другие являются перезаписываемыми (переменные) или исполнимыми (инструкции). Кроме этого, отдельные процессы могут получать доступ только к тем областям памяти, которые им принадлежат.
Внутри ядра адресное пространство процесса вместе со всей связанной с ним информацией хранится в описателе iran_s truct. Вы можете вспомнить из гл. 3, «Процессы: принципиальная модель выполнения», что эти структуры связаны с task_struct процесса. Область памяти представляется описателем vm_area_struct. Каждый описатель области памяти описывает представляемый им последовательный интервал адресов. На протяжении этого раздела мы будем называть описатель интервала адресов описате-
Глава 4• Управление памятью
лем области памяти или vms_area_struct. Теперь рассмотрим mm_struct и vm_area_struct. Рис. 4.10 иллюстрирует связь между этими двумя структурами.
task_struct | ||||||||||||||||||
vm_area_struct | vm_area_struct | |||||||||||||||||
mm | ||||||||||||||||||
vm_mm [- | vm_mm [■ | vm_mm | ||||||||||||||||
vm_next |- | vm_next [ | vm_next | ||||||||||||||||
inll_ | mm mm_struct | mm. | struct | mm_struct | mm_struct | |||||||||||||
mmap | mmap | mmap | mmap | |||||||||||||||
mmjist | mmjist | mmjist | mmjist | |||||||||||||||
Рис. 4.10. Структуры памяти, связанные с процессом
4. 7 A mm_struct
Каждая задача имеет структуру mm__struct (include/linux/sched.h), используемую ядром для представления диапазона адресов. Все описатели mm_struct хранятся в дву связном списке. Головой списка является структура mm_struct, соответствующая процессу 0, которым является процесс ожидания. Доступ к этому описателю можно получить через глобальную переменную init_mm:
include/linux/sched.h
185 struct ram_struct {
186 struct vm__area_struct * mmap;
187 struct rb_root mm_rb;
188 struct wi_area_struct * mmap_cache;
189 unsigned long free_area_cache;
190 pgd_t * pgd;
191 atomic_t mra_users;
192 atomic_t mm_count;
193 int map_count;
194 struct rw_seraaphore mmap_sem;
195 spinlock_t page_table_lock 196
197 struct list_head mmlist;
2 02 unsigned long start.jcode, end_code, start_data, end_data;
Структуры памяти процесса в Linux
203 unsigned long start_brk, brk, start_stack;
2 04 unsigned long arg_start, arg_end, env_start, env_end;
2 05 unsigned long rss, total_vm, locked_vm;
2 06 unsigned long def_flags,-
2 07 cpuma sk_t cpu_vm_ma s k;
2 08 unsigned long swap_address;
228 };
Mmap
Описатель области памяти (определенный в следующем подразделе), назначаемый процессу, помещается в список. Доступ к этому списку можно получить через поле mmap mm__struct. Перемещаться по списку можно с помощью поля vm_next каждой из структур vma_area_struct.
4.7.1.2 mm_rb
Простой связанный список позволяет легко перемещаться по всем описателям областей памяти, соответствующим определенным процессам. Тем не менее, если ядро ищет описатель области памяти конкретного процесса, простой список не обеспечивает достаточной скорости поиска. Поэтому структуры, связанные с диапазоном адресов конкретного процесса, также хранятся в красно-белом дереве, доступ к которому можно получить через поле mm_rb. Таким образом, увеличивается скорость поиска ядром конкретного описателя области памяти.
4.7.1.3 mmap_cache
mmap_cache - это указатель на последнюю область памяти, связанную с процессом. Принцип локальности (principle of locality)предполагает, что при обращении к области памяти, наиболее часто используемые области памяти расположены ближе. При этом высока вероятность, что требуемый в данный момент адрес принадлежит той же области памяти, которой принадлежит и предыдущий затребованный адрес. Вероятность того, что текущий адрес находится в запрашиваемой перед этим области, составляет примерно 35 процентов.
Pgd
Поле pgd - это указатель на глобальную директорию страницы, которая хранит запись для этой области памяти. В mm_struct для ожидающего процесса (процесс 0) это поле указывает на swapper_pg_dir. (См. более подробную информацию в разд. 4.9 о том, на что указывают поля этой структуры.)
Глава 4• Управление памятью
4.7.1.5 mm_user
Поле mm_struct хранит количество процессов, получивших доступ к этой области памяти. Легковесные процессы или потоки разделяют некоторые интервалы адресов и областей памяти. Поэтому mm_struct для потоков обычно имеют поле mm_users со значением больше 1. Этим полем можно управлять с помощью атомарных функций atomic_set() , atomic_dec_and__lock() , atomic_read() и atomic_inc ().
4.7.1.6 mm_count
mm_count - это количество использований mm_s truct. При определении возможности освобождения этой структуры делается проверка данного поля. Если оно содержит значение 0, то эта структура не используется процессами и, следовательно, ее можно освободить.
4.7.1.7 map_count
Поле map_count хранит количество областей памяти или описателей vma_area_ struct в адресном пространстве процесса. Каждый раз, когда в адресное пространство процесса добавляется новая область памяти, это поле увеличивается одновременно со вставкой vms_area_struct в список mmap и дерево mm_rb.
Mmjist
Поле iran_list типа list_head хранит адреса соседних mm_struct в списке описателей памяти. Как говорилось ранее, голова списка указывает на глобальную переменную init_mm, являющуюся описателем процесса 0. При работе с этим списком mmlist_ lock защищает эту структуру от постороннего доступа.
Следующие 11 полей описывают работу с различными типами областей памяти, выделяемыми для процесса. Вместо того чтобы пускаться в подробное объяснение их отличий от ранее описанных структур, связанных с процессом, мы ограничимся общим описанием.
4.7.1.9 start_code и end_code
Поля start_code и end_code хранят начальный и конечный адреса блока кода региона процессорной памяти (т. е. выполняемый текстовый сегмент).
4.7.1.10 start_data и end_data
Поля start_data и end_data содержат начальный и конечный адреса инициализированных данных (которые находятся в части . data исполняемого файла).
4.7.1.11 stackj>rk и brk
Поля stack_brk и brk хранят начальный и конечные адреса кучи процесса.
4.7 Структуры памяти процесса в Linux
4.7.1.12 stack_stack
stack_stack является начальным адресом стека процесса.
4.7.1.13 arg_start и arg_end
Поля arg_start и arg__end хранят начальный и конечный адреса аргументов, передаваемых процессу.
4.7.1.14 env_start и env_end
Поля env_start и env_end хранят начальный и конечный адреса раздела переменных окружения.
Это касается поля mm_struct, которое мы рассматриваем в этой главе. Теперь посмотрим на поля описателя области памяти, vm_area_struct.
4.7.2 vm_area_struct
Структура vm_area_s true t определяет регион виртуальной памяти. Процесс обладает несколькими регионами памяти, на каждый из которых приходится по одной структуре vm_area_strue t:
include/linux/mm.h
51 struct vm_area_struct {
52 struct mm__struct * vm_mm;
53 unsigned long vm_start;
54 unsigned long vm_end;
57 struct vm_area_struct *vm__next;
60 unsigned long vm__flags;
62 struct rbjiode vm_rb;
72 struct vm_operations_struct * vm_ops;
};
Vmjnm
Все регионы памяти принадлежат к адресному пространству, связанному с процессом и представляемому mm_struct. Структура vm_iran указывает на структуру типа mm_struct, описывающую адресное пространство, к которому принадлежит данная область памяти.
Глава 4• Управление памятью
4.7.2.2 vm_start и vm_end
Регионы памяти связаны с интервалами адресов. В vm_area_struct этот интервал определяется таким образом, чтобы следить за начальным и конечным адресом интервала. В целях увеличения производительности начальный адрес региона памяти должен быть кратным размеру фрейма страницы. Ядро следит, чтобы фреймы страниц заполнялись данными из определенного региона памяти, размер которого также является кратным размеру фрейма страницы.
Vrrwiext
Поле vm_next указывает на следующую vm_area_struct в связанном списке, содержащем все регионы в адресном пространстве процесса. Голова этого списка определена для адресного пространства в поле mmap структуры nim__struct.
Vmjlags
Внутри этого интервала регион памяти связан с описывающими его характеристиками. Они хранятся в поле vm_f lags и применяются к страницам в регионе памяти. Табл. 4.6 описывает доступные флаги.
Таблица 4.6. Значения vm_area_struct->vmjlags
Флаг
Описание
VM_READ VM_WRITE VM_EXEC VM_SHARED
VM_GROWSDOWN
VM_GROWSUP
VM_DENYWRITE
VM_EXECUTABLE
VM_LOCKED
VM_DONTCOPY
VM DNTEXPANDa