В чем смысл key_t, если ключом к доступу к общей памяти является возвращаемое значение shmget()?
При использовании разделяемой памяти, почему мы должны заботиться о создании ключа
key_t ftok(const char *path, int id);
в следующем бите кода?
key_t key;
int shmid;
key = ftok("/home/beej/somefile3", 'R');
shmid = shmget(key, 1024, 0644 | IPC_CREAT);
Из того, что я понял, для доступа к данной разделяемой памяти требуется shmid
, а не ключ. Или я ошибаюсь? Если нам нужно shmid
, то в чем смысл не только создавать случайный ключ каждый раз?
Изменить
@Beej Руководство по Unix IPC можно прочитать:
Как насчет этого key
ерунды? Как мы его создаем? Ну, так как тип key_t
на самом деле просто a long
, вы можете используйте любое количество, которое вы хотите. А вдруг вы скорректировали число и некоторые другие несвязанные жесткие коды программы то же число, но хочет другую очередь? Решение состоит в использовании ftok()
функция, которая генерирует ключ из два аргумента.
Считая это, создается впечатление, что то, что нужно прикрепить к блоку с разделяемой памятью, - это ключ. Но это не так, не так ли?
Ответы
Ответ 1
Да, вам нужно использовать shmid для доступа к общей памяти (используя shmat()
) после ее открытия с помощью shmget()
. Но конкретный блок разделяемой памяти, к которому вы будете обращаться, основан на ключе, который вы используете, то есть другой процесс, желающий общаться через shm, должен будет использовать один и тот же ключ. Если вы просто использовали случайное число в качестве ключа, вы можете столкнуться с какой-либо другой несвязанной программой.
Я собирался предложить взглянуть на Beej Guide to IPC, но я вижу, что вы уже нашли его:)
Ответ 2
Вся система System V IPC полна плохих конструкций, подобных этому. (По плохим проектам я имею в виду крошечное пространство имен для общих ресурсов, где вам нужно полагаться на глупые трюки, такие как ftok
, чтобы получить ключ и молиться, чтобы он не конфликтует с другими используемыми ключами.)
Если возможно, я бы притворился, что он не существует и вместо этого использует общую память POSIX (и аналогичные примитивы синхронизации потоков POSIX вместо семафоров System V). Единственный экземпляр, который я могу вспомнить о том, где вам нужна системная память V, - это расширение образа общей памяти X и, возможно, другие расширения X.
Изменить: Чтобы лучше ответить на вопрос OP о цели ftok
: key_t
, как правило, 32-битный, и да, вы могли бы просто выбрать 32-битное число самостоятельно, но проблема в том, что люди не одинаково склонны выбирать все числа, и вероятность столкновения слишком высока. ftok
позволяет вам выбрать файл (который должен быть уникальным для вашего приложения), а целое число и хэш-номер файла inode с выбранным вами целым числом, что должно привести к гораздо более равномерному распределению ключевых вариантов в ключевом пространстве. Конечно, вы также можете просто выбрать ключ с rand
, если у вас есть способ передать результат другим процессам, которым необходимо присоединить общую память.
Ответ 3
Значения shmid
действительны только в контексте одного процесса, тогда как одно и то же значение key_t
в разных процессах позволит им открыть один и тот же сегмент разделяемой памяти.
По сути, вам нужен key_t
- как способ перекрестного процесса наименования сегмента разделяемой памяти. Что касается ftok()
, как отмечали другие ответы, это использовалось для уменьшения вероятности двух несвязанных групп процессов с использованием того же значения key_t
.