next up previous contents
Next: Потоки (threads). Up: Разделяемые сегменты памяти Previous: Управление разделяемыми сегментами памяти.   Contents

Операции над разделяемыми сегментами памяти.

В справочной статье shmop синтаксис системных вызовов shmat и shmdt описан так:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmat (int shmid, char *shmaddr, int shmflg);

int shmdt (char *shmaddr);

При успешном завершении системного вызова shmat() результат равен адресу, который получил присоединенный сегмент; в случае неудачи возвращается -1.

Разумеется, чтобы использовать результат shmat() как указатель, его нужно преобразовать к требуемому типу.

В качестве аргумента shmid должен выступать идентификатор разделяемого сегмента, предварительно полученный при помощи системного вызова shmget. Аргумент shmaddr задает адрес, по которому сегмент должен быть присоединен, то есть тот адрес в виртуальном пространстве пользователя, который получит начало сегмента. Не всякий адрес является приемлемым. Можно порекомендовать адреса вида

0x80000000

0x80040000

0x80080000

. . .

Если значение shmaddr равно нулю, система выбирает адрес присоединения по своему усмотрению.

Аргумент 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);

}

Рис. 23. Операции над сегментами разделяемой памяти.


next up previous contents
Next: Потоки (threads). Up: Разделяемые сегменты памяти Previous: Управление разделяемыми сегментами памяти.   Contents
2003-12-09