SHMOP(2) | Руководство программиста Linux | SHMOP(2) |
shmat, shmdt - операции с общей памятью System V
#include <sys/types.h> #include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
Вызов shmat() подключает сегмент общей памяти System V с идентификатором shmid к адресному пространству вызывающего процесса. Адрес подключения, указанный в shmaddr, учитывается следующим образом:
В дополнении к SHM_RND, в аргументе битовой маски shmflg могут быть указаны следующие флаги:
Значение brk(2) вызывающего процесса от подключения не изменяется. При завершении работы процесса сегмент будет автоматически отсоединён. Один и тот же сегмент может быть подключён в адресное пространство процесса несколько раз, как только для чтения, так и для чтения-записи.
При успешном выполнении системный вызов shmat() обновляет поля структуры shmid_ds (см. shmctl(2)), связанной с общим сегментом памяти, следующим образом:
Вызов shmdt() отключает сегмент общей памяти, находящийся по адресу shmaddr, от адресного пространства вызывающего процесса. Отключаемый сегмент должен быть подключён по адресу shmaddr с помощью вызова shmat().
При успешном выполнении вызов shmdt() обновляет поля структуры shmid_ds, связанной с общим сегментом памяти, следующим образом:
При успешном выполнении shmat() возвращается адрес подключённого общего сегмента памяти; при ошибке возвращается (void *) -1, а в errno содержится код ошибки.
При успешном выполнении shmdt() возвращается 0; при ошибке возвращается -1, а в errno содержится код ошибки.
Значения errno, устанавливаемые при возникновении ошибок в shmat():
Значения errno, устанавливаемые при возникновении ошибок в shmdt():
POSIX.1-2001, POSIX.1-2008, SVr4.
В SVID 3 (возможно, чуть раньше) тип аргумента shmaddr изменён с char * на const void *, а тип возвращаемого значения shmat() с char * на void *.
При вызове fork(2) потомки наследуют подключённые общие сегменты памяти.
При вызове execve(2) все подключённые общие сегменты памяти отключаются.
При вызове _exit(2) все подключённые общие сегменты памяти отключаются.
Для улучшения переносимости программ при подключении общего сегмента памяти рекомендуется использовать shmat() с аргументом shmaddr, установленным в NULL. Необходимо учитывать, что сегмент памяти, подключаемый таким способом, в разных процессах может подключаться по разным адресам. Поэтому все указатели в области общей памяти должны быть не абсолютными, а относительными (как правило относительно адреса начала сегмента).
В Linux сегмент общей памяти можно подключить даже, если он помечен для удаление. Однако в POSIX.1 об этом ничего не сказано, и многие другие реализации это не поддерживают.
На работу shmat() влияют следующие системные параметры:
Реализацией не ограничивается количество общих сегментов общей памяти на процесс (SHMSEG).
brk(2), mmap(2), shmctl(2), shmget(2), capabilities(7), shm_overview(7), svipc(7)
2017-09-15 | Linux |