Проектирование очереди как разделяемой памяти

Я пытаюсь спроектировать/внедрить (циклическую) очередь (в C) в качестве общей памяти, чтобы ее можно было использовать между несколькими потоками/процессами.

Структура очереди следующая:

typedef struct _q {
    int q_size;
    int q_front;
    int q_rear;
    int *q_data;
}queue;

Который поддерживает следующие функции:

int empty_q(queue *q);
int display_q(queue *q);
int create_q(queue **q, int size);
int delete_q(queue **q);
int enqueue(queue *q, int data);
int dequeue(queue *q, int *data);

В соответствии с размером очереди, указанным пользователем, память для q_data будет выделена в create_q().

Вопрос: Как создать разделяемую память для этой очереди, используя системные функции, представленные в "sys/shm.h"? Любой фрагмент кода/пример для создания/присоединения/извлечения/удаления разделяемой памяти для структуры данных очереди с использованием shmget(), shmat(), shmctl() и т. д. был бы большим подспорьем.


person Sangeeth Saravanaraj    schedule 12.12.2011    source источник
comment
Если вы хотите обмениваться процессами с помощью механизма, похожего на очередь, не лучше ли использовать очереди сообщений? Для потоков одного и того же процесса будет достаточно стандартной очереди, защищенной критическим разделом.   -  person dario_ramos    schedule 12.12.2011
comment
Очереди сообщений @dario_ramos были бы идеальным решением этой проблемы ... но я пытаюсь привести пример с использованием очереди, чтобы узнать, как прикрепить структуру данных с общей памятью.   -  person Sangeeth Saravanaraj    schedule 12.12.2011
comment
В этом случае, когда я возился с Unix IPC, я следовал руководству Beej по Unix IPC. Там даже есть шутки! Вы можете перейти непосредственно к разделу с общей памятью.   -  person dario_ramos    schedule 12.12.2011
comment
Я добавил последний комментарий в качестве ответа, так как я немного проверил руководство, и в нем есть именно то, что вам нужно.   -  person dario_ramos    schedule 12.12.2011


Ответы (2)


Когда я возился с Unix IPC, я следовал руководству Beej по Unix IPC. Там даже есть шутки! Вы можете перейти непосредственно к разделу общей памяти. В нем есть фрагменты, объясняющие каждый шаг, и полный пример в конце.

person dario_ramos    schedule 12.12.2011
comment
Гид Биджа потрясающий. Спасибо, что поделился. :) - person Sangeeth Saravanaraj; 15.12.2011
comment
Я также сослался на это ‹kohala.com/start/unpv22e/unpv22e.chap12.pdf› .. относительно хорошая информация. - person Sangeeth Saravanaraj; 16.12.2011
comment
Похоже на более подробную ссылку, хорошо для вас. Небольшая деталь: удалите ‹ и › из вашей ссылки, иначе она не будет работать (я мог видеть документ, потому что я редактировал URL) - person dario_ramos; 16.12.2011

Вот простой пример, который создает разделяемую память размером со структуру, записывает в нее некоторые данные и распечатывает их. Запустите один экземпляр, и он создаст общую память и поместит в нее некоторые «данные», а затем дождется нажатия клавиши. Запустите второй экземпляр в другой командной строке, и второй экземпляр распечатает содержимое памяти.

typedef struct
   {
   char a[24];
   int i;
   int j;
   } somestruct;


void fillshm(int shmid) {
   somestruct *p;

   if ( (p = shmat (shmid, NULL, 0)) < 0 )
      {
      perror("shmat");
      exit(1);
      }

   printf("writing to shared memory\n");
   strcpy(p->a, "my shared memory");
   p->i = 123;
   p->j = 456;
}


void printshm(int shmid)
{
   somestruct *p;
   if ( (p = shmat (shmid, NULL, 0)) < 0 )
      {
      perror("shmat");
      exit(1);
      }

   printf( "%s, %d, %d\n", p->a, p->i, p->j );
}

int main( int argc, char *argv[] ) {

   int shmid;

   // see if the memory exists and print it if so
   if ( (shmid = shmget (1234, 0, 0)) >= 0 )
      printshm( shmid );
   else
      {
      // didn't exist, so create it
      if ( (shmid = shmget (1234, sizeof( somestruct ), IPC_CREAT | 0600)) < 0 )
         {
         perror("shmget");
         exit(1);
         }

      printf( "shmid = %d\n", shmid );

      fillshm(shmid);
      printf( "Run another instance of this app to read the memory... (press a key): " );
      getchar();

      // delete it
      if ( shmctl (shmid, IPC_RMID, NULL) < 0 )
         {
         perror("semctl");
         exit(1);
         }
      }

   return 0;
}
person Mark Wilkins    schedule 12.12.2011
comment
Спасибо за пример. Это правильно (но неполно). Любая идея о том, как прикрепить/связать структуру с общей памятью? - person Sangeeth Saravanaraj; 12.12.2011
comment
@SangeethSaravanaraj: назначьте память указателю на структуру. То же, что память от вызова malloc. Вам нужно убедиться, что каждый процесс имеет идентичное определение структуры (с одинаковой упаковкой). - person Mark Wilkins; 12.12.2011
comment
@SangeethSaravanaraj: Ради интереса я обновил пример, чтобы использовать структуру и сделать его немного более интересным (разрешить запуск двух экземпляров, один из которых заполняет память, а другой печатает ее). - person Mark Wilkins; 14.12.2011
comment
Спасибо за ваши усилия. Ваш фрагмент кода дал мне несколько хороших советов для выполнения моей задачи. +1 - person Sangeeth Saravanaraj; 15.12.2011