Инициализация мьютекса pthread в разделяемой памяти - PullRequest
2 голосов
/ 01 ноября 2010

Я могу инициализировать мьютекс в статической памяти с помощью инициализатора:

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

но как мне инициализировать один в общей памяти, где я должен выделить память отдельно от инициализации переменной? Могу ли я сделать memcpy ()?

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
memcpy(&globalmutex, &mymutex, sizeof(mymutex);

Мне показалось, что я вспомнил, как читал давным-давно, что при распределении мьютекса в памяти, гарантированно инициализируемого нулями, он не нуждается в инициализации - предназначенной именно для этого случая - но я не могу найти записанное в любом месте. Это действительно так? - Я заметил, что PTHREAD_MUTEX_INITIALIZER определен как {{0, 0, 0, 0, 0, 0, {0, 0}}} в моей системе redhat.

Ответы [ 2 ]

4 голосов
/ 01 ноября 2010

Здесь нужно быть осторожным, не все реализации поддерживают мьютексы, которые могут работать между процессами.

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

Вместо этого вам нужно будет использовать pthread_mutex_init() после правильного построения структуры атрибутов мьютекса:

int pthread_mutex_init(
    pthread_mutex_t *mutex,
    const pthread_mutexattr_t *attr);

Лучше всего будет просто выделить место в общей памятиприведите его к правильному типу и передайте его функции init.Я думаю, что это может быть безопаснее, чем копировать его после инициализации.

1 голос
/ 04 ноября 2017

У меня похожая проблема, и один из подходов, которые я использую, - это попытка исключительно создать общую память с (O_CREAT | O_RDWR | O_EXCL). Если создание завершилось успешно, инициализируйте мьютекс в разделяемой памяти. Если это не удалось, проверьте, существует ли общая память. Если разделяемая память существует, просто откройте ее с флагом O_RDWR и сопоставьте ее с мьютексом, но предположите, что она уже была инициализирована процессом, который успешно ее создал. Вот немного псевдокода (POSIX + pthreads):

/* semaphore POST (block access from other processes) */
/* try to exclusively create */
int fd = shm_open (name, (O_CREAT | O_RDWR | O_EXCL), (S_IRUSR | S_IWUSR));
if (fd == -1) {
    /* failed creation */
    /* semaphore WAIT (wait until mutex initialized) */
    if (errno == EEXIST) {
        /* already exists, try to open */
        fd = shm_open (name, O_RDWR, (S_IRUSR | S_IWUSR));
        if (fd == -1) {
            /* check errors */
        } else {
            /* optionally check shared data size with fstat */
            fstat () ...
            /* map */
            mmap () ...
        }
    } else {
        /* check create errors */
    }
} else {
    /* successful creation! */
    /* truncate */
    ftruncate () ...
    /* map */
    mmap () ...
    /* initialize mutex */
    pthread_mutexattr_init () ...
    pthread_mutexattr_setpshared ( ... , PTHREAD_PROCESS_SHARED ) ...
    pthread_mutex_init () ...
    /* semaphore WAIT (wait until all processes are finished) */
}

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

Редактировать

Подумав немного, я понимаю, что защита семафоров IPC может быть лучше в качестве мьютекса, и тогда мы должны рекурсивно создать мьютекс общей памяти. А если серьезно, то может сработать единственный процесс, который управляет исключительно созданием, инициализацией и уничтожением защитного мьютекса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...