У меня похожая проблема, и один из подходов, которые я использую, - это попытка исключительно создать общую память с (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 может быть лучше в качестве мьютекса, и тогда мы должны рекурсивно создать мьютекс общей памяти. А если серьезно, то может сработать единственный процесс, который управляет исключительно созданием, инициализацией и уничтожением защитного мьютекса.