2013-12-10 4 views
3

Я в настоящее время переношу существующий код Win32 в Linux. В Windows у меня есть «главный» процесс, «читатель», который создает объект общей памяти, а затем ожидает, что некоторые «подчиненные» процессы, «писатели», помещают данные в разделяемую память для обработки.Использование fstat между shm_open и mmap

Мастер-процесс: реализация Win32 основана на CreateFileMapping(INVALID_HANDLE_VALUE, [...], а затем на MapViewOfFile. Размер общей памяти si, указанный в вызове CreateFileMapping. Передача 0 в качестве последнего аргумента в MapViewOfFile обеспечивает отображение всей общей памяти. В Linux после некоторых поисковых запросов я пришел к выводу, что должен использовать shm_open + ftruncate + mmap.

Подчиненных процессы: реализация Win32, почти такие же, как и в процессе Master, за исключением того, что CreateFileMapping заменяется OpenFileMapping, и что VirtualQuery может быть использован для получения размера совместно используемой памяти.

В Linux у меня проблема: «подчиненные» процессы должны как-то «подождать» для завершения вызова ftruncate в «основном» процессе. Они не могут делать ftruncate сами по себе, так как у них еще нет идей об объеме общей памяти.

Было бы нормально, если процессы «ведомого» были опросом на fstat beetwen shm_open и mmap? Или это плохая практика, и если да, есть ли другой способ «хорошего» размера?

EDIT:

В настоящее время, я не хочу, чтобы напрямую использовать файловую систему. Мне нравится, что я могу создать «Именованный общий объект памяти», используя «имя», которое будет работать на двух платформах, как "/MySharedMemName42" и не хочет заботиться о местоположении (-ях) файла (ов). Я могу изменить свое мнение, если оно кажется нереалистичным.

Я знаю, что мастер-процесс и подчиненные процессы должны взаимодействовать при использовании общей памяти. Они делают это с записью/чтением памяти. «Проблема» в том, что shm_open/mmap может привести к SIGBUS в подчиненных устройствах, если есть расы (ftruncate опоздал в мастер). Я тестировал, что «fstat pollling» делает трюк, но хочет знать, считается ли это ужасным взломом или правильным способом справиться с гонкой.

+0

Как вы разрешить гонки между 'CreateFileMapping' в master и' OpenFileMapping' в подчиненных? – chill

+0

@chill Какая гонка? Если OpenFileMapping терпит неудачу, ведомые выполняют то, что они хотят (повторите?). Если OpenFileMapping завершится успешно, они могут MapViewOfFile без страха. – manuell

+0

Ключом к любому из этого является взаимодействие процессов. Некоторые системы имеют отдельный процесс в начале и в конце дня для создания и развязки их разделяемой памяти до запуска приложений (серва или клиента). Некоторые из них имеют механизмы (например, блокировки файлов, семафор и т. Д.) Для координации упорядоченной загрузки процессов, например. нет сервера, тогда клиенты не запускаются. – Duck

ответ

2

Если я правильно понимаю, то вызов для Windows CreateFileMapping является атомной версии строфы UNIX «shm_open + ftruncate + возможно-ММАП», таким образом, возможность на UNIX, что клиенты могут получить доступ к общей памяти перед тем он имеет надлежащий размер.

Итак, ваше предлагаемое использование fstat в порядке. Это officially supported с помощью опции общей памяти POSIX. Кажется, что ваш дизайн терпит опрос о существовании области разделяемой памяти, поэтому опрос для правильного его размера (или, по крайней мере, st_size > 0) также должен быть в порядке.

В качестве альтернативы, вы могли бы, возможно, играть в режиме разделяемой области памяти во время открытой (O_CREAT | O_EXCL и 0600) и fchown его, когда готовы - ваши подчиненные процессы, в зависимости от UIDs и GID, в потерпит неудачу с ENOENT или EACCES, пока память не будет подготовлена. Опять же, это опция «опроса». Вы также можете переименовать общую память (через Linux /dev/shm/) после ее калибровки, но это удобство, отличное от POSIX.

(Теперь, если ваши подчиненные детей мастеров, то вы могли бы полагаться на этой почтенной * NIX технике наследования процесса и переключиться на безымянную разделяемую память ...)

+0

Даже с разрешениями у вас все еще есть условия гонки. Суть в том, что если size == 0 (как и на вновь созданном сегменте), клиент должен отступить (как-то) или выйти. Или полностью избегайте ситуации, не запуская клиентов без сервера. – Duck

+0

CreateFileMapping - это атомная версия «shm_open + ftruncate». mmap выполняется с помощью MapViewOfFile. Благодарю. – manuell

+0

@ Дак, какая раса вы имеете в виду? Нет расы, если подчиненные не могут успешно выполнить shm_open() 'сегмент до тех пор, пока он не будет' ftruncate() 'd. (Мастер должен создать объект shm исключительно.) – pilcrow

0

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

В случае Windows у вас есть подчиненные устройства, пытающиеся открыть сопоставление файлов с известным известным именем и повторить попытку, если сопоставление с этим именем не существует.

Хотя это не идеальное решение, но вы можете сделать то же самое в Linux.

Обратите внимание, что вам необязательно нужен объект общей памяти POSIX. Вы можете использовать обычный файл. Сначала создайте и задайте размер файла с помощью обычных open(2) и ftruncate(2), но с использованием временных уникальных случайных символов. Затем rename(2) файл от имени temp до известного имени.

+0

См. Обновленный вопрос. Мои ведомые Windows не могут сбой при нарушении памяти, когда они успешно открывают объект в гонке с мастером. Является ли ваша идея переименования применимой к объекту общей памяти POSIX? – manuell

+0

Правда, на обеих платформах существует одно и то же условие гонки, но я не уверен, где вы идете с идеей файла. – Duck

+0

@Duck Я не вижу гонки *, приводящей к сбою * в версии win32. – manuell

Смежные вопросы