В чем смысл 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.