Читать интересную книгу UNIX: взаимодействие процессов - Уильям Стивенс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 77 78 79 80 81 82 83 84 85 ... 128

13.3. Функции ftruncate и fstat

Размер файла или объекта разделяемой памяти можно изменить вызовом ftruncate:

#include <unistd.h>

int ftruncate(int fd, off_t length);

/* Возвращает 0 в случае успешного завершения, –1 – в случае ошибки */

Стандарт Posix делает некоторые различия в определении действия этой функции для обычных файлов и для объектов разделяемой памяти.

1. Для обычного файла: если размер файла превышает значение length, избыточные данные отбрасываются. Если размер файла оказывается меньше значения length, действие функции не определено. Поэтому для переносимости следует использовать следующий способ увеличения длины обычного файла: вызов 1 seek со сдвигом length-1 и запись 1 байта в файл. К счастью, почти все реализации Unix поддерживают увеличение размера файла вызовом ftruncate.

2.  Для объекта разделяемой памяти: ftruncate устанавливает размер объекта равным значению аргумента length.

Итак, мы вызываем ftruncate для установки размера только что созданного объекта разделяемой памяти или изменения размера существующего объекта. При открытии существующего объекта разделяемой памяти следует воспользоваться fstat для получения информации о нем:

#include <sys/types.h>

#include <sys/stat.h>

int fstat(int fd, struct stat *buf);

/* Возвращает 0 в случае успешного завершения. –1 – в случае ошибки */

В структуре stat содержится больше десятка полей (они подробно описаны в главе 4 [21]), но только четыре из них содержат актуальную информацию, если fd представляет собой дескриптор области разделяемой памяти:

struct stat {

 …

 mode_t st_mode; /* mode: S_I{RW}{USR,GRP,OTH} */

 uid_t st_uid; /* UID владельца */

 gid_t st_gid; /* GID владельца */

 off_t st_size; /* размер в байтах */

 …

};

Пример использования этих двух функций будет приведен в следующем разделе. 

ПРИМЕЧАНИЕ

К сожалению, стандарт Posix никак не оговаривает начальное содержимое разделяемой памяти. Описание функции shm_open гласит, что «объект разделяемой памяти будет иметь нулевой размер». Описание ftruncate гласит, что для обычных файлов (не объектов разделяемой памяти) «при увеличении размера файла он будет дополнен нулями». Однако в этом описании ничего не говорится о содержимом разделяемой памяти. Обоснование Posix.1 (Rationale) говорит, что «разделяемая память при расширении дополняется нулями», но это не официальный стандарт. Когда автор попытался уточнить этот вопрос в конференции comp.std.unix, он узнал, что некоторые производители протестовали против введения требования на заполнение памяти нулями из-за возникающих накладных расходов. Если новая область памяти не инициализируется каким-то значением (то есть содержимое остается без изменения), это может угрожать безопасности системы.

13.4. Простые программы

Приведем несколько примеров программ, работающих с разделяемой памятью Posix.

Программа shmcreate

Программа shmcreate, текст которой приведен в листинге 13.1,[1] создает объект разделяемой памяти с указанным именем и длиной.

Листинг 13.1. Создание объекта разделяемой памяти Posix указанного размера

//pxshm/shmcreate.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int c, fd, flags;

6   char *ptr;

7   off_t length;

8   flags = O_RDWR | O_CREAT;

9   while ((c = Getopt(argc, argv, "e")) != –1) {

10   switch (c) {

11   case 'e':

12    flags |= O_EXCL;

13    break;

14   }

15  }

16  if (optind != argc – 2)

17   err_quit("usage: shmcreate [ –e ] <name> <length>");

18  length = atoi(argv[optind + 1]);

19  fd = Shm_open(argv[optind], flags, FILE_MODE);

20  Ftruncate(fd, length);

21  ptr = Mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

22  exit(0);

23 }

19-22 Вызов shm_open создает объект разделяемой памяти. Если указан параметр –е, будет возвращена ошибка в том случае, если такой объект уже существует. Вызов ftruncate устанавливает длину (размер объекта), a mmap отображает его содержимое в адресное пространство процесса. Затем программа завершает работу. Поскольку разделяемая память Posix обладает живучестью ядра, объект разделяемой памяти при этом не исчезает.

Программа shmunlink

В листинге 13.2 приведен текст тривиальной программы, удаляющей имя объекта разделяемой памяти из системы.

Листинг 13.2. Удаление имени объекта разделяемой памяти Posix

//pxshm/shmunlink.c

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5  if (argc != 2)

6   err_quit("usage: shmunlink <name>");

7  Shm_unlink(argv[1]);

8  exit(0);

9 }

Программа shmwrite

В листинге 13.3 приведен текст программы shmwrite, записывающей последовательность 0, 1, 2 254, 244, 0, 1 и т. д. в объект разделяемой памяти.

Листинг 13.3. Заполнение разделяемой памяти

//pxshm/shmwrite.с

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int i, fd;

6   struct stat stat;

7   unsigned char *ptr;

8   if (argc != 2)

9    err_quit("usage: shmwrite <name>");

10  /* open, определяем размер, отображаем в память */

11  fd = Shm_open(argv[1], O_RDWR, FILE_MODE);

12  Fstat(fd, &stat);

13  ptr = Mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE,

14   MAP_SHARED, fd, 0);

15  Close(fd);

16  /* присваиваем: ptr[0] = 0, ptr[1] = 1 и т. д. */

17  for (i = 0; i < stat.st_size; i++)

18   *ptr++ = i % 256;

19  exit(0);

20 }

10-15 Объект разделяемой памяти открывается вызовом shm_open. Его размер мы узнаем с помощью fstat. Затем файл отображается в память вызовом mmap, после чего его дескриптор может быть закрыт.

16-18 Последовательность записывается в разделяемую память.

Программа shmread

Программа shmread (листинг 13.4) проверяет значения, помещенные в разделяемую память программой shmwrite.

Листинг 13.4. Проверка значений в разделяемой памяти

//pxshm/shmread.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int i, fd;

6   struct stat stat;

7   unsigned char c, *ptr;

8   if (argc != 2)

9    err_quit("usage: shmread <name>");

10  /* вызываем open, узнаем размер, отображаем в память*/

11  fd = Shm_open(argv[1], O_RDONLY, FILE_MODE);

12  Fstat(fd, &stat);

13  ptr = Mmap(NULL, stat.st_size, PROT_READ,

14   MAP_SHARED, fd, 0);

15  Close(fd);

16  /* проверяем равенства ptr[0] = 0, ptr[1] = 1 и т. д. */

17  for (i = 0; i < stat.st_size; i++)

18   if ((c = *ptr++) != (i % 256))

19    err_ret("ptr[%d] = %d", i, c);

20  exit(0);

21 }

10-15 Объект разделяемой памяти открывается только для чтения, его размер получается вызовом fstat, после чего он отображается в память с доступом только на чтение, а дескриптор закрывается.

16-19 Проверяются значения, помещенные в разделяемую память вызовом shmwrite.

Примеры

Создадим объект разделяемой памяти с именем /tmp/myshm объемом 123 456 байт в системе Digital Unix 4.0B:

alpha % shmcreate /tmp/myshm 123456

alpha % ls –l /tmp/myshm

-rw-r--r-- 1 rstevens system 123456 Dec 10 14:33 /tmp/myshm

alpha % od –c /tmp/myshm

0000000

*

0361100

Мы видим, что файл с указываемым при создании объекта разделяемой памяти именем появляется в файловой системе. Используя программу od, мы можем выяснить, что после создания файл целиком заполнен нулями (восьмеричное число 0361100 — сдвиг, соответствующий байту, следующему за последним байтом файла, — эквивалентно десятичному 123 456).

Запустим программу shmwrite и убедимся в правильности записываемых значений с помощью программы od:

alpha % shmwrite /tmp/myshm

alpha * od –x /tmp/myshm | head-4

0000000 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e

0000020 1110 1312 1514 1716 1918 1b1a 1d1c 1f1e

0000040 2120 2322 2524 2726 2928 2b2a 2d2c 2f2e

0000060 3130 3332 3534 3736 3938 3b3a 3d3c 3f3e

alpha % shmread /tmp/myshm

alpha % shmunlink /tmp/myshm

Мы проверили содержимое разделяемой памяти и с помощью shmread, а затем удалили объект, запустив программу shmunlink.

Если теперь мы запустим программу shmcreate в Solaris 2.6, то увидим, что файл указанного размера создается в каталоге /tmp:

1 ... 77 78 79 80 81 82 83 84 85 ... 128
На этом сайте Вы можете читать книги онлайн бесплатно русская версия UNIX: взаимодействие процессов - Уильям Стивенс.

Оставить комментарий