В справочной статье shmop синтаксис системных вызовов shmat и shmdt описан так:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmat (int shmid, char *shmaddr, int shmflg);
int shmdt (char *shmaddr);
Разумеется, чтобы использовать результат shmat() как указатель, его нужно преобразовать к требуемому типу.
В качестве аргумента shmid должен выступать идентификатор разделяемого сегмента, предварительно полученный при помощи системного вызова shmget. Аргумент shmaddr задает адрес, по которому сегмент должен быть присоединен, то есть тот адрес в виртуальном пространстве пользователя, который получит начало сегмента. Не всякий адрес является приемлемым. Можно порекомендовать адреса вида
0x80040000
0x80080000
. . .
Аргумент shmflg используется для передачи системному вызову shmat() флагов SHM_RND и SHM_RDONLY. Наличие первого из них означает, что адрес shmaddr следует округлить до некоторй системно-зависимой величины. Второй флаг предписывает присоединить сегмент только для чтения; если он не установлен, присоединенный сегмент будет доступен и на чтение, и на запись (если процесс обладает соответствующими правами).
При успешном завершении системного вызова shmdt() результат равен нулю; в случае неудачи возвращается -1.
Аргумент shmaddr задает начальный адрес отсоединяемого сегмента. После того, как последний процесс отсоединил разделяемый сегмент памяти, этот сегмент вместе с идентификатором и ассоциированной структурой данных следует удалить с помощью системного вызова shmctl.
Пример использования вызовов shmat() и shmdt() приведен ниже (рис. 23):
возможности системных вызовов shmat() и shmdt()
(операции над разделяемыми сегментами памяти) */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
main ()
{
extern int errno;
int shmid, shmaddr, shmflg;
int flags, attach, detach, rtrn, i;
/* Цикл присоединений для данного процесса */
printf ("\nВведите число присоединений ");
printf ("для процесса (1-4): ");
scanf ("%d", &attach);
printf ("\nЧисло присоединений = %d\n", attach);
for (i = 0; i < attach; i++) {
/* Ввести идентификатор разделяемого сегмента */
printf ("\nВведите ид-р разделяемого сегмента,\n");
printf ("над которым нужно выполнить операции: ");
scanf ("%d", &shmid);
printf ("\nИд-р сегмента = %d\n", shmid);
/* Ввести адрес присоединения */
printf ("\nВведите адрес присоединения ");
printf ("в шестнадцатеричной записи: ");
scanf ("%x", &shmaddr);
printf ("\nАдрес присоединения = 0x%x\n", shmaddr);
/* Выбрать требуемые флаги */
printf ("\nВведите номер нужной комбинации флагов:\n");
printf (" SHM_RND = 1\n");
printf (" SHM_RDONLY = 2\n");
printf (" SHM_RND и SHM_RDONLY = 3\n");
printf (" Выбор = ");
scanf ("%d", &flags);
switch (flags) {
case 1:
shmflg = SHM_RND;
break;
case 2:
shmflg = SHM_RDONLY;
break;
case 3:
shmflg = SHM_RND | SHM_RDONLY;
break;
}
printf ("\nФлаги = 0%o", shmflg);
/* Выполнить системный вызов shmat */
rtrn = shmat (shmid, shmaddr, shmflg);
if (rtrn == -1) {
printf ("\nshmat завершился неудачей!\n");
printf ("\Код ошибки = %d\n", errno);
}
else {
printf ("\nshmat завершился успешно.\n");
printf ("Идентификатор shmid = %d\n", shmid);
printf ("Адрес = 0x%x\n", rtrn);
}
}
/* Цикл отсоединений для данного процесса */
printf ("\nВведите число отсоединений ");
printf ("для процесса (1-4): ");
scanf ("%d", &detach);
printf ("\nЧисло отсоединений = %d\n", detach);
for (i = 0; i < detach; i++) {
/* Ввести адрес отсоединения */
printf ("\nВведите адрес отсоединяемого сегмента ");
printf ("в шестнадцатеричной записи: ");
scanf ("%x", &shmaddr);
printf ("\nАдрес отсоединения = 0x%x\n", shmaddr);
/* Выполнить системный вызов shmdt */
rtrn = shmdt (shmaddr);
if (rtrn == -1) {
printf ("\nshmdt завершился неудачей!\n");
printf ("\Код ошибки = %d\n", errno);
}
else {
printf ("\nshmdt завершился успешно,\n");
printf ("идентификатор shmid = %d\n", shmid);
}
}
exit (0);
}