воскресенье, 27 ноября 2011 г.

Использование общей памяти

Есть много способов обеспечить взаимодействие процессов, в этой статье я расскажу об одном из них, об использовании общей памяти.

Функции, которые мы будем использовать:
  • int shmget(key_t KEY, size_t SIZE, int FLAGS);
Функция, выделяющая общую память. Возвращает идентефикатор сегмента или -1.
Аргументы:
KEY - ключ сегмента. Константа IPC_PRIVATE инициирует динамическое выделение ключа.
SIZE - Запрашиваемое число байт для сегмента.
FLAGS - Права доступа к сегменту. Также есть дополнительные флаги: IPC_CREAT - создать, IPC_EXCL - написать что сегмент уже создан.
  • void* shmat(int ID, void* ADDRESS, int FLAGS);
Функция для получения доступа к выделенному сегменту. Возвращает адрес или (void *) -1.
Аргументы:
ID - идентификатор сегмента. 
ADDRESS - адрес, по которому доступен сегмент. В случае NULL выбирается произвольный.
FLAGS - дополнительные флаги.
  • shmdt(void* ADDRESS);
Функция для завершения работы с общей памятью. Возвращает 0 или -1(при ошибке).
  • int shmctl(int ID, int COMMAND, struct shmid_ds * DESC);
Функция для осуществления различных операций над памятью . Возвращает 0 или -1.
Аргументы:
ID - идентификатор сегмента.
COMMAND - выполняемая команда, часто это IPC_STAT - получить данные и IPC_RMID - удалить сегмент.
DESC - указатель на структуру, в которую заносятся данные о сегменте. Для IPC_RMID достаточно NULL.

Использование общей памяти
Рассмотрим пример:
owner создаёт общий сегмент с импользование ключа IPC_PRIVATE, заносит туда данные и открывает доступ к нему для всех желающих. user подключается, используя ключ сегмента и читает данные из сегмента.

/* Файл owner.c */
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>

#define SHMEM_SIZE 4096
#define SH_MESSAGE "test\n"

int
main(void)
{
  int shm_id, shm_size;
  char* shm_buf;
  struct shmid_ds ds;

  shm_id = shmget(IPC_PRIVATE, SHMEM_SIZE, IPC_CREAT | IPC_EXCL | 0600);
  if(shm_id == -1)
  {
    fprintf(stderr, "shmget()\n");
    return 1;
  }

  shm_buf = (char *) shmat(shm_id, NULL, 0);
  if(shm_buf == (char *) -1)
  {
    fprintf(stderr, "shmat()\n");
    return 1;
  }

  shmctl(shm_id, IPC_STAT, &ds);

  shm_size = ds.shm_segsz;
  if(shm_size < strlen(SH_MESSAGE))
  {
    fprintf(stderr, "error\n");
    return 1;
  }

  strcpy(shm_buf, SH_MESSAGE);

  printf("ID: %d\n", shm_id);
  printf("Enter");
  fgetc(stdin);

  shmdt(shm_buf);
  shmctl(shm_id, IPC_RMID, NULL);

  return 0;
}  





/* Файл user.c */
#include <sys/shm.h>
#include <stdio.h>

int
main(int argc, char ** argv)
{
  int shm_id;
  char* shm_buf;
  
  if(argc < 2)
  {
    fprintf(stderr, "error(argc)\n");
    return 1;
  }

  shm_id = atoi(argv[1]);
  shm_buf = (char *) shmat(shm_id, 0, 0);
  if(shm_buf == (char*) -1)
  {
    fprintf(stderr, "shmat()\n");
    return 1;
  }

  printf("%s\n", shm_buf);
  shmdt(shm_buf);

  return 0;
}

Вот что получилось:

Использование общей памяти
Использование общей памяти - owner

Использование общей памяти
Использование общей памяти - user


Система: FreeBSD 8.2

Комментариев нет:

Отправить комментарий