shihappns Ответов: 2

Общая память Linux. Отправка нескольких сообщений.


Эта программа генерирует два сообщения в общей памяти. Я хочу, чтобы сообщения хранили разные данные. Когда я запускаю эту программу я получаю вот это:
Данные, записанные в сообщении 1: это сообщение 1
Данные, записанные в сообщении 2: это сообщение 1

Но в нем не должно быть текста стр2 потому что строка "это сообщение 1" записывается только в ул.


Программа печатает в str2 то же сообщение, что и str. Как это исправить?





 #include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdio.h> 

int main() 
{ 
//MESSAGE1
    // ftok to generate unique key 
    key_t key = ftok("shmfile",65); 
  
    // shmget returns an identifier in shmid 
    int shmid = shmget(key,1024,0666|IPC_CREAT); 
  
    // shmat to attach to shared memory 
    char *str = (char*) shmat(shmid,(void*)0,0); 
  
  strcpy(str,"This is message 1");
  
    printf("Data written in message 1: %s\n",str); 
      

    //MESSAGE2
    
    // ftok to generate unique key 
    key_t key2 = ftok("shmfile2",77); 
  
    // shmget returns an identifier in shmid 
    int shmid2 = shmget(key2,1024,0666|IPC_CREAT); 
  
    // shmat to attach to shared memory 
    char *str2 = (char*) shmat(shmid2,(void*)0,0); 
     printf("Data written in message2: %s\n",str2); 
    
    
    
  
    return 0; 
}


Что я уже пробовал:

Я пытался использовать разные ключи, разные shmid, но опять же второе сообщение имеет те же данные, что и первое. И если я пишу что-то в str2, это перезаписывает первое сообщение str. У меня есть reader.c, где я хочу напечатать два разных сообщения.

2 Ответов

Рейтинг:
2

Rick York

Я использую общую память много и для самых разных вещей. Единственное, что вы не можете сделать с ним, - это сохранить указатели, потому что указатель в адресном пространстве одного процесса недопустим для другого процесса. Однако вы можете сохранять и использовать смещения между процессами. В любом случае, я обычно "сопоставляю" структуру данных с общей памятью. Это так же просто, как просто наведение указателя на данные вашей структуры. Вы можете объявить структуру практически с любым типом данных, которые вам нужны, хотя указатели не рекомендуются. Вот один из примеров:

const size_t BufferSize = 63;
typedef TextBuffer[BufferSize+1];

typedef struct
{
    int         InCount;
    int         OutCount;
    TextBuffer  String1;
    TextBuffer  String2;
    float       Float1;
    float       Float2;
    double      Double1;
    double      Double2;
} SmMemData;

// attach to the shared memory and 'map' it to the data

ShMemData *psmd = (ShMemData *) shmat(shmid,(void*)0,0);
Как уже упоминал Ричард, вам нужен механизм контроля доступа к данным. В этом примере один процесс может увеличивать InCount каждый раз, когда он вводит новые данные, а другой процесс увеличивает OutCount каждый раз, когда он обрабатывает данные. Это только одна возможность, и вы можете адаптировать данные и логику, чтобы сделать то, что вам нужно.


Рейтинг:
15

Richard MacCutchan

// shmat to attach to shared memory
char *str2 = (char*) shmat(shmid2,(void*)0,0);
 printf("Data written in message2: %s\n",str2);

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


shihappns

Да, но когда я пишу что-то в str2, это перезаписывает данные. У меня есть программа reader.c, в которой я хочу распечатать эти два сообщения. Например Скрыть   скопировать кодСкрыть   скопировать код

 strcpy(str2,"This is message 2");
в writer.c и в reader.c я печатаю первое сообщение - str, а затем оно показывает мне: это сообщение 2. Разве они не должны быть в разных блоках памяти?

Richard MacCutchan

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

shihappns

Я снял отсоединение, но происходит то же самое. Как их синхронизировать?

Richard MacCutchan

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