Внутреннее устройство ядра Linux 2.4




Sys_shmat()


Функция sys_shmat() принимает в качестве параметров ID сегмента разделяемой памяти, адрес по которому должен быть присоединен сегмент (shmaddr) и флаги, котроые описаны ниже.

Если параметр shmaddr не нулевой и установлен флаг SHM_RND, то shmaddr округляется "вниз" до ближайшего кратного SHMLBA. Если shmaddr не кратен SHMLBA и флаг SHM_RND не установлен, то возвращается код ошибки EINVAL.

Производится проверка прав доступа вызывающего процесса, после чего поле shm_nattch сегмента разделяемой памяти увеличивается на 1. Увеличение этого поля гарантирует сегмент разделяемой памяти от ликвидации, пока он присоединен к сегменту памяти процесса. Эти операции выполняются после установки глобальной блокировки разделяемой памяти.

Вызывается функция do_mmap(), которая отображает страницы сегмента разделяемой памяти на виртуальное адресное пространство. Делается это под семафором mmap_sem текущего процесса. В функцию do_mmap() передается флаг MAP_SHARED, а если вызывающий процесс передал ненулевое значение shmaddr, то передается и флаг MAP_FIXED. В противном случае do_mmap() самостоятельно выберет виртуальный адрес для сегмента разделяемой памяти.

ВАЖНО Из do_mmap() будет вызвана функция через структуру shm_file_operations. Эта функция вызывается для установки PID, текущего времени и увеличения счетчика присоединений данного сегмента разделяемой памяти.

После вызова do_mmap() приобретается глобальный семафор и глобальная блокировка разделяемой памяти. Счетчик присоединений затем уменьшается на 1, уменьшение производится потому, что в вызове счетчик был увеличен на 1. Если после уменьшения счетчик стал равен нулю и если сегмент имеет метку SHM_DEST, то вызывается для ликвидации сегмента разделяемой памяти.

В заключение в вызывающую программу возвращается виртуальный адрес разделяемой памяти. Если функция do_mmap() вернула код ошибки, то этот код будет передан как возвращаемое значение системного вызова.




Содержание  Назад  Вперед