Выбрать главу

■ информацию о файловой системе, к которой относится полное имя pathname (поле st_dev структуры stat);

■ номер узла (i-node) в файловой системе (поле st_ino структуры stat);

■ младшие 8 бит идентификатора (который не должен равняться нулю).

Из комбинации этих трех значений обычно получается 32-разрядный ключ. Нет никакой гарантии того, что для двух различных путей с одним и тем же идентификатором получатся разные ключи, поскольку количество бит информации в трех перечисленных элементах (идентификатор файловой системы, номер узла, идентификатор IPC) может превышать число бит в целом (см. упражнение 3.5).

ПРИМЕЧАНИЕ

Номер узла всегда отличен от нуля, поэтому большинство реализаций определяют константу IPC_PRIVATE (раздел 3.4) равной нулю.

Если указанное полное имя не существует или недоступно вызывающему процессу, ftok возвращает значение –1. Помните, что файл, имя которого используется для вычисления ключа, не должен быть одним из тех, которые создаются и удаляются сервером в процессе работы, поскольку каждый раз при создании заново эти файлы получают, вообще говоря, другой номер узла, а это может изменить ключ, возвращаемый функцией ftok при очередном вызове.

Пример

Программа в листинге 3.1 принимает полное имя в качестве аргумента командной строки, вызывает функции stat и ftok, затем выводит значения полей st_dev и st_ino структуры stat и получающийся ключ IPC. Эти три значения выводятся в шестнадцатеричном формате, поэтому легко видеть, как именно ключ IPC формируется из этих двух значений и идентификатора 0x57.

Листинг 3.1[1]. Получение и вывод информации о файле и созданного ключа IPC

//svipc/ftok.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   struct stat stat;

6   if (argc != 2)

7    err_quit("usage: ftok <pathname>");

8   Stat(argv[1], &stat);

9   printf("st_dev: &lx, st_ino: %Ix, key: %x\n",

10   (u_long) stat.st_dev, (u_long) stat.st_ino,

11   Ftok(argv[1], 0x57));

12  exit(0);

13 }

Выполнение этой программы в системе Solaris 2.6 приведет к следующим результатам:

solaris %ftok /etc/system

st_dev: 800018, st_ino: 4a1b, key: 57018a1b

solaris %ftok /usr/tmp

st_dev: 800015, st_ino: 10b78, key: 57015b78

solaris %ftok /home/rstevens/Mail.out

st_dev: 80001f, st_ino: 3b03, key: 5702fb03

Очевидно, идентификатор определяет старшие 8 бит ключа; младшие 12 бит st_dev определяют следующие 12 бит ключа, и наконец, младшие 12 бит st_ino определяют младшие 12 бит ключа.

Цель этого примера не в том, чтобы впоследствии рассчитывать на такой способ формирования ключа из перечисленной информации, а в том, чтобы проиллюстрировать алгоритм комбинации полного имени и идентификатора конкретной реализацией. В других реализациях алгоритм может быть другим.

ПРИМЕЧАНИЕ

В FreeBSD используются младшие 8 бит идентификатора, младшие 8 бит st_dev и младшие 16 бит st_ino.

Учтите, что отображение, производимое функцией ftok, — одностороннее, поскольку часть бит st_dev и st_ino не используются. По данному ключу нельзя определить полное имя файла, заданное для вычислений.

3.3. Структура ipc_perm

Для каждого объекта IPC, как для обычного файла, в ядре хранится набор информации, объединенной в структуру.

struct ipc_perm {

 uid_t uid; /*идентификатор пользователя владельца*/

 gid_t gid; /*идентификатор группы владельца */

 uid_t cuid; /*идентификатор пользователя создателя*/

 gid_t cgid; /*идентификатор группы создателя*/

 mode_t mode; /*разрешения чтения-записи*/

 ulong_t seq; /*последовательный номер канала*/

 key_t key; /* ключ IPC */

}

Эта структура вместе с другими переименованными константами для функций System V IPC определена в файле <sys/ipc.h>. В этой главе мы расскажем о полях структуры ipc_perm более подробно.

3.4. Создание и открытие каналов IPC

Три функции getXXX, используемые для создания или открытия объектов IPC (табл. 3.1), принимают ключ IPC (типа key_t) в качестве одного из аргументов и возвращают целочисленный идентификатор. Этот идентификатор отличается от того, который передавался функции ftok, как мы вскоре увидим. У приложения есть две возможности задания ключа (первого аргумента функций getXXX):

1. Вызвать ftok, передать ей полное имя и идентификатор.

2. Указать в качестве ключа константу IPCPRIVATE, гарантирующую создание нового уникального объекта IPC.

Последовательность действий иллюстрирует рис. 3.1. 

Рис. 3.1. Вычисление идентификаторов IPC по ключам

Все три функции getXXX (табл. 3.1) принимают в качестве второго аргумента набор флагов oflag, задающий биты разрешений чтения-записи (поле mode структуры ipc_perm) для объекта IPC и определяющий, создается ли новый объект IPC или производится обращение к уже существующему. Для этого имеются следующие правила.

■ Ключ IPC_PRIVATE гарантирует создание уникального объекта IPC. Никакие возможные комбинации полного имени и идентификатора не могут привести к тому, что функция ftok вернет в качестве ключа значение IPC_PRIVATE.

■ Установка бита IPC_CREAT аргумента oflag приводит к созданию новой записи для указанного ключа, если она еще не существует. Если же обнаруживается существующая запись, возвращается ее идентификатор. 

Одновременная установка битов IPC_CREAT и IPC_EXCL аргумента oflag приводит к созданию новой записи для указанного ключа только в том случае, если такая запись еще не существует. Если же обнаруживается существующая запись, функция возвращает ошибку EEXIST (объект IPC уже существует).

Комбинация IPC_CREAT и IPC_EXCL в отношении объектов IPC действует аналогично комбинации O_CREAT и O_EXCL для функции open.

Установка только бита IPC_EXCL без IPC_CREAT никакого эффекта не дает.

Логическая диаграмма последовательности действий при открытии объекта IPC изображена на рис. 3.2. В табл. 3.2 показан альтернативный взгляд на этот процесс.

Рис. 3.2. Диаграмма открытия объекта IPC

Обратите внимание, что в средней строке табл. 3.2 для флага IPC_CREAT без IPC_EXCL мы не получаем никакой информации о том, был ли создан новый объект или получен доступ к существующему. Для большинства приложений характерно создание сервером объекта IPC с указанием IPC_CREAT (если безразлично, существует ли уже объект) или IPC_CREAT | IPC_EXCL (если требуется проверка существования объекта). Клиент вообще не указывает флагов, предполагая, что сервер уже создал объект.

ПРИМЕЧАНИЕ

Функции System V IPC в отличие от функций Posix IPC определяют свои собственные константы IРС_ххх вместо использования O_CREAT и OEXCL, принимаемых стандартной функцией open (табл. 2.2).

вернуться

1

Все исходные тексты, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com/download.