Общая память не обновляется синхронно - PullRequest
3 голосов
/ 11 июня 2019

Для моего проекта у меня есть две задачи: 1) Writer: записать значение в структуру в общей памяти 2) Reader: прочитать значение из структуры

Вот код писателя

struct test {
    volatile int read;
    volatile int write;
};

int main() 
{ 
    // 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 
    struct test *t = (struct test *) shmat(shmid,(void*)0,0); 
    printf("Going to write into test structure"); 

    t->read = 1;
    t->write = 2;

    //printf("Data written in memory: %s\n",str); 

    //detach from shared memory 
    shmdt((void *)t); 

    return 0; 
} 

Вот код читателя

int main() 
{ 
    // 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 
    struct test *t = (struct test *) shmat(shmid,(void*)0,0); 
    printf("Data read from memory: %d:%d\n",t->read,t->write); 

    //detach from shared memory 
    shmdt((void *)t); 

    // destroy the shared memory 
    shmctl(shmid,IPC_RMID,NULL); 

    return 0; 
} 

Когда я сначала запускаю писатель, а затем читатель, все работает нормально.

Но для отладки я попытался запустить оба одновременно через lldb.Я вижу, если писатель пишет t-> read = 1, в то же время он не будет обновляться в процессе чтения.После того, как изменения сделаны, в читателе будет отражено, вызывает ли он shmat.

Может ли кто-нибудь сказать мне, как сделать так, чтобы изменения в общей памяти происходили синхронно?

1 Ответ

0 голосов
/ 11 июня 2019
   "It would reflect in reader if it calls shmat after changes are done."

Я думаю, что последовательность, в которой вызывается shmat в процессах чтения и записи, не имеет значения. Единственное, что нужно гарантировать, - это что-то записывается в общую память до того, как процесс чтения начинает читать. Это может быть достигнуто с помощью обычных механизмов IPC, таких как семафоры, как указано в разделе комментариев. Я проверил ваш код с помощью GDB. Сначала я запустил процесс записи с помощью gdb и приостановил процесс записи после 't-> read = 1;' заявление. В этот момент я выполнил процесс чтения, и он успешно прочитал значение 1.

Я провел несколько других тестов, в которых процесс чтения вызывает shmat, прежде чем процесс записи сделал, и нашел похожие результаты.

Единственное, на что я хочу обратить внимание, это то, что порядок вызова shmat не имеет значения, если запись происходит до чтения.

Я добавляю ответ на ваши комментарии здесь, так как он слишком длинный, чтобы поместиться в разделе комментариев:

Я опробовал шаги, которые вы предложили, и получил ожидаемый результат, то есть значение 't-> read' в процессе чтения равно 1. Я использую следующие команды для компиляции моего кода: gcc -g -o writer write. c и gcc -g -o читатель read.c. Опция -g предназначена для включения символов отладки. После этого я использовал gdb для запуска процессов записи и чтения и добавил точки останова в операторах printf. Таким образом, процессы чтения и записи были приостановлены в операторе printf. Затем я выполнил 't-> read = 1' в писателе. После этого я проверил дамп памяти в обоих процессах. Оба отражали 1. Затем я напечатал значение t-> read в считывателе, которое правильно показало 1.

...