Доступ к общей памяти без семафоров - PullRequest
1 голос
/ 05 октября 2009

с использованием apis совместно используемой памяти в linux. Если у меня одна запись (процессом A) и только одна запись (процессом B), мне все еще нужен семафор.?. Есть ли пример, чтобы показать, что использование совместного использования памяти без семафора попадет в тупик в Linux.

Ответы [ 4 ]

3 голосов
/ 05 октября 2009

Ваш вопрос немного странный. Прежде всего, вам НЕ НУЖНО использовать семафоры, так как существуют другие методы синхронизации.

Во-вторых, отказ от использования семафора обычно не приводит к взаимоблокировке (если у вас не было семафора, защищающего блокировку или другой метод синхронизации по какой-либо причине). ИСПОЛЬЗОВАНИЕ методов синхронизации имеет тенденцию вызывать взаимоблокировки, а не их отсутствие.

Однако, когда у вас есть писатель (и) и читатель (и), борющиеся за один и тот же ресурс, вы можете иметь так называемое Состояние гонки

Теперь к вашему вопросу об одном писателе и одном читателе: это можно сделать с помощью мьютексов вместо семафоров или любого другого числа методов синхронизации. В качестве альтернативы, если вы можете гарантировать, что записи B-процесса являются атомарными (то есть они не могут оставить общую память в несогласованном состоянии при прерывании), синхронизация не требуется. Последний сценарий маловероятен, если общая память не может быть обновлена ​​с помощью одной инструкции (а иногда даже этого недостаточно). Вам будет лучше просто выбрать безопасный маршрут и каким-то образом заблокировать доступ к общей памяти.

3 голосов
/ 05 октября 2009

Без семафоров (или, в более общем случае, MUTEX) не может быть взаимоблокировок. Однако могут произойти противоречивые / несогласованные данные.

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

For example:
Original text
    "The British are coming!"
Thread 1 start changing to "Warn all patriots!" but only gets to write the 
first 8 characters.  Then...
Thread 2 reads
    "Warn allish are coming!

Редактировать : См. Ответ Фалаины, который обычно повторяет этот, и предоставляет указатели и определения для связанных понятий: условия расы, атомность, мьютекс ...

0 голосов
/ 05 октября 2009

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

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

#include <semaphore.h>
class ScopedLock{
    sem_t *sem;
public:
    ScopedLock(const char* name) : sem(0)
    {
        sem = sem_open(name, O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, 1);
        if (sem == SEM_FAILED)
        {
            printf("Error opening semaphore : %s\n", last_error_message());
            throw "failed to create semaphore";
        }

        printf("locking interprocess lock...\n");
        if (-1 == sem_wait(sem))
        {
            printf("Error locking semaphore : %s\n", last_error_message());
            throw "failed to lock semaphore";
        }
        printf("interprocess lock locked\n");
    }

    ~ScopedLock()
    {
        if (sem)
        {
            sem_post(sem);
            printf("interprocess lock unlocked\n");
        }
    }

    // static destroy function, use for cleanup
    static void destroy(const char *name)
    {
        sem_t *sem = sem_open(name, O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
        if (sem != SEM_FAILED)
        {
            sem_post(sem);
            sem_destroy(sem);
        }

        if (-1 == sem_unlink(name))
        {
            printf("Error destroying semphore: %s\n", last_error_message());
        }
    }
};
0 голосов
/ 05 октября 2009

С одной записью процесса вы не сможете попасть в тупик.

Однако читатель должен иметь возможность иметь дело с частично записанными данными во время чтения. И это вполне может быть невозможно.

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

...