Эквивалент Windows с именем mutex в Mac OS X?

В настоящее время я переношу программное обеспечение из Windows в Mac OS X на С++.

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

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

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

Есть ли в Mac OS X/Linux поддержка отказа от mutex?

Я исследовал библиотеку boost, библиотека boost имеет именованный mutex, но она основана на общем файле, поэтому она не имеет отказавшегося состояния.

Пожалуйста, дайте мне несколько советов.

2 ответа

Возможно, немного поздно, но вы можете использовать pthread_mutexattr_t, чтобы настроить атрибут mutex для обмена между pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED); API. Это значение мьютекса должно делиться между процессами, сохраняя его в именованной разделяемой памяти.

Вот фрагмент кода:

int key = ftok(NAMED_MEMORY, ID_TAG);
if (-1 == key)
{
 printf("Unable to name shared memory\n");
 exit(1);
}
// Create the segment exclusively (if the segment already exists then a combination of IPC_CREAT | IPC_EXCL returns an error EEXIST)
int m_iShmid = shmget(key, TOTAL_SIZE, READ_WRITE_PERMISSIONS | IPC_CREAT | IPC_EXCL);
if (m_iShmid < 0)
{
 if (EEXIST == errno)
 {
 // if the shared memory already exists we only fetch the id to that memory
 m_iShmid = shmget(key, TOTAL_SIZE, READ_WRITE_PERMISSIONS);
 }
 if (m_iShmid < 0)
 {
 printf("Unable to create shared memory - %s\n",strerror(errno));
 exit(1);
 }
 else
 printf("Attached to the existing shared memory\n");
}
else
 printf("Created new shared memory\n");
// Now we attach the segment to our data space.
mutex = reinterpret_cast<pthread_mutex_t*>(shmat(m_iShmid, NULL, 0));
if (reinterpret_cast<pthread_mutex_t*>(-1) == mutex)
{
 printf("Unable to attach shared memory to the process - %s\n",strerror(errno));
 exit(1);
}
// Now we can set this mutex to be shared between processes
pthread_mutex_t* mutex;
pthread_mutexattr_t mutexAttr;
ret = pthread_mutexattr_init(&mutexAttr);
if(ret != 0)
{
 printf("pthread_mutexattr_init failed - err=%d\n",ret);
 exit(1);
}
ret = pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
if(ret != 0)
{
 printf("pthread_mutexattr_setpshared failed - err=%d\n",ret);
 exit(1);
}
ret = pthread_mutexattr_setrobust_np(&mutexAttr, PTHREAD_MUTEX_ROBUST_NP);
if(ret != 0)
{
 printf("pthread_mutexattr_setrobust_np failed - err=%d\n",ret);
 exit(1);
}
ret = pthread_mutex_init(mutex, &mutexAttr);
if(ret != 0)
{
 printf("pthread_mutex_init failed - err=%d\n",ret);
 exit(1);
}
// ------ Use the mutex from here on between processes
</pthread_mutex_t*></pthread_mutex_t*>


Учитывая, что единственный ответ здесь использует древний подход ftok()/shmget() для получения разделяемой памяти, я собираюсь указать вам на библиотеку, которую я разрабатываю и поддерживаю:

https://github.com/cubiclesoft/cross-platform-cpp

В частности, вам нужны файлы sync/sync_mutex. * и sync/sync_util. *. Вы получаете Windows, Mac, Linux и, возможно, несколько вариантов тех, у кого есть один класс Sync:: Mutex, с использованием современных POSIX pthreads и общей памяти POSIX для именованных объектов в * ОС в стиле NIX. Код также обрабатывает сценарии, такие как только один поток создает и инициализирует объект, а другие потоки ожидают, пока объект не будет полностью инициализирован, прежде чем продолжить.

Часть Sync библиотеки, используемая для использования семафоров POSIX, но я обнаружил, что они сильно нарушены на некоторых ОС, в то время как разделяемая память и pthreads используют более широкую поддержку на тех же ОС.

Что касается оставленных состояний, то сама ОС должна взять на себя ответственность за объекты синхронизации для обработки этого конкретного сценария. То есть, процесс завершается, и все приобретенные объекты синхронизации становятся отмеченными как заброшенные. Ядро Windows обычно обрабатывает очистку объектов синхронизации при выходе из процесса. Другие ядра ОС не будут/не могут этого сделать. Один из возможных вариантов - написать системную услугу или драйвер для других ОС, единственной целью которых является обращение с оставленными состояниями и очистка и повторная инициализация объектов. Конечно, если вы выясните отличный способ обработки заброшенных объектов из самого приложения, сообщите мне/отправьте патч/и т.д.

licensed under cc by-sa 3.0 with attribution.