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

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

Cинтаксис системных вызовов 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():

/* Программа иллюстрирует

возможности системных вызовов 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);

}


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