11  nloop = atoi(argv[1]);

12  /* открываем /dev/zero и отображаем в память */

13  fd = Open("/dev/zero", O_RDWR);

14  ptr = Mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

15  Close(fd);

6-11 Автоматическая переменная zero больше не используется, как и аргумент командной строки, задававший имя создаваемого файла.

12-15 Мы открываем файл /dev/zero и передаем его дескриптор функции mmap. Область памяти будет гарантированно проинициализирована нулями.

<p>12.6. Обращение к объектам, отображенным в память</p>

Когда в память отображается обычный файл, размер полученной области (второй аргумент вызова mmap), как правило, совпадает с размером файла. Например, в листинге 12.3 размер файла устанавливается равным размеру структуры shared вызовом write и это же значение размера области используется при отображении его в память. Однако эти два параметра — размер файла и размер области памяти, в которую он отображен, — могут и отличаться.

Для детального изучения особенностей функции mmap воспользуемся программой в листинге 12.6.

Листинг 12.6. Отображение файла: размер файла совпадает с размером области памяти

//shra/test1.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int fd, i;

6   char *ptr;

7   size_t filesize, mmapsize, pagesize;

8   if (argc != 4)

9    err_quit("usage: test1 pathname filesize mmapsize");

10  filesize = atoi(argv[2]);

11  mmapsize = atoi(argv[3]);

12  /* открытие файла, установка его размера */

13  fd = Open(argv[1], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);

14  Lseek(fd, filesize-1, SEEK_SET);

15  Write(fd, "", 1);

16  ptr = Mmap(NULL, mmapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

17  Close(fd);

18  pagesize = Sysconf(_SC_PAGESIZE);

19  printf("PAGESIZE = %ld\n", (long) pagesize);

20  for (i = 0; i max(filesize, mmapsize); i += pagesize) {

21   printf("ptr[*d] = %d\n", i, ptr[i]);

22   ptr[i] = 1;

23   printf("ptr[%d] = %d\n", i + pagesize – 1, ptr[i + pagesize – 1]);

24   ptr[i + pagesize – 1] = 1;

25  }

26  printf("ptr[%d] = %d\n", i, ptr[i]);

27  exit(0);

28 }

Аргументы командной строки

8-11 Аргументы командной строки задают полное имя создаваемого и отображаемого в память файла, его размер и размер области памяти.

Создание, открытие, урезание файла; установка его размера

12-15 Если файл не существует, он будет создан. Если он существует, его длина будет установлена равной нулю. Затем размер файла устанавливается равным указанному размеру путем вызова lseek для установки текущей позиции, равной трe-буемому размеру минус 1 и записи 1 байта.

Отображение файла в память

16-17 Файл отображается в память, причем размер области задается последним аргументом командной строки. Затем дескриптор файла закрывается.

Вывод размера страницы памяти

18-19 Размер страницы памяти получается вызовом sysconf и выводится на экран.

Чтение и запись в область отображения

20-26 Считываются и выводятся данные из области памяти, в которую отображен файл. Считываются первый и последний байты каждой страницы этой области памяти. Все значения должны быть нулевыми. Затем первый и последний байты каждой страницы устанавливаются в 1. Одно из обращений к памяти может привести к отправке сигнала процессу, что приведет к его завершению. После завершения цикла for мы добавляем еще одно обращение к следующей странице памяти, что должно заведомо привести к ошибке и завершению пpoгрaммы (если ошибка не возникла раньше).

Рассмотрим первую ситуацию: размер файла совпадает с размером области памяти, но эта величина не кратна размеру страницы памяти в данной реализации:

solaris % ls –l foo

foo: No such file or directory

solaris % test1 foo 5000 5000

PAGESIZE = 4096

ptr[0] = 0

ptr[4095] = 0

ptr[4096] = 0

ptr[8191] = 0

Segmentation Fault(coredump)

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже