Опубликован: 06.12.2004 | Доступ: свободный | Студентов: 1180 / 143 | Оценка: 4.76 / 4.29 | Длительность: 20:58:00
ISBN: 978-5-9556-0021-5
Лекция 7:

Асинхронный ввод/вывод, рекомендательные интерфейсы

< Лекция 6 || Лекция 7: 12345 || Лекция 8 >

Функция posix_fallocate() резервирует долговременную память для указанной части файла. После успешного завершения ее работы запись в эту часть файла не может кончиться неудачей из-за нехватки свободного пространства.

Если сумма ( offset + len ) превышает текущий размер файла, он будет соответственно увеличен; в противном случае размер не изменится.

Влияние предыдущих вызовов posix_fadvise() на стратегию выделения долговременной памяти зависит от реализации.

Функция posix_madvise() информирует реализацию об ожидаемом поведении приложения по отношению к части адресного пространства вызывающего процесса, которая начинается с адреса addr и имеет длину len байт. Подобная информация может оказаться полезной, если в указанную область памяти отображен файл. (Реализация имеет право требовать, чтобы область начиналась с границы страницы.)

Ожидаемое поведение специфицирует аргумент advice, который может принимать следующие значения.

POSIX_MADV_NORMAL

Подразумеваемое поведение – отсутствие рекомендаций.

POSIX_MADV_SEQUENTIAL

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

POSIX_MADV_RANDOM

Специфицирует случайный доступ.

POSIX_MADV_WILLNEED

Предполагается, что данные из указанной части адресного пространства скоро понадобятся.

POSIX_MADV_DONTNEED

Предполагается, что данные из указанной части адресного пространства в ближайшее время не понадобятся.

Функция posix_memalign() служит для резервирования области памяти длины size с начальной границей, выровненной в соответствии со значением аргумента alignment. Результирующий адрес записывается по указателю memptr. Значение alignment должно быть кратным величине sizeof (void *), которая является степенью двойки.

Область памяти, зарезервированную посредством вызова posix_memalign(), в дальнейшем можно освободить с помощью функции free().

При оптимизации обмена данными с файлами, наряду с применением рекомендательных интерфейсов, целесообразно учитывать значения следующих конфигурационных констант, определенных в заголовочном файле <limits.h>, которые можно опросить, обращаясь к функции pathconf().

POSIX_ALLOC_SIZE_MIN

Минимальное число байт долговременной памяти, реально выделяемое для любой части файла.

POSIX_REC_MIN_XFER_SIZE

Минимальное рекомендуемое число передаваемых байт при обмене данными с файлами. Рекомендуется также, чтобы и смещение передаваемой порции данных от начала файла было кратным POSIX_REC_MIN_XFER_SIZE.

POSIX_REC_MAX_XFER_SIZE

Максимальное рекомендуемое число передаваемых байт при обмене данными с файлами.

POSIX_REC_INCR_XFER_SIZE

Рекомендуемое приращение числа передаваемых байт при обмене данными с файлами (в диапазоне от POSIX_REC_MIN_XFER_SIZE до POSIX_REC_MAX_XFER_SIZE ).

POSIX_REC_XFER_ALIGN

Рекомендуемое значение для выравнивания границы буфера обмена данными с файлами.

Применение функций рекомендательных интерфейсов проиллюстрируем программой, подсчитывающей сумму байт в файле (см. листинг 7.10).

/* * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Программа подсчитывает сумму байт в файле –   */
/* аргументе командной строки,   */
/* пытаясь оптимизировать чтение данных с помощью   */
/* функций               */
/* рекомендательных интерфейсов   */
/* * * * * * * * * * * * * * * * * * * * * * * * * * */

#define _XOPEN_SOURCE 600

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main (int argc, char *argv []) {
  int fd;       /* Дескриптор файла-аргумента   */
  long sum = 0;   /* Сумма байт в файле   */
  char *pbuf;     /* Указатель на буфер обмена   */
  ssize_t nb;     /* Число прочитанных байт   */
  int i;

  if (argc != 2) {
    fprintf (stderr, "Использование: %s имя_файла\n", 
      argv [0]);
    return (1);
  }

  /* Откроем заданный файл на чтение */
  if ((fd = open (argv [1], O_RDONLY)) == -1) {
    perror ("OPEN");
    return (2);
  }

  /* Опишем дисциплину работы с файлом */

  if (((errno = posix_fadvise (fd, 0, 0, 
      POSIX_FADV_SEQUENTIAL)) != 0) || ((errno = 
      posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE)) != 0)) {
    perror ("POSIX_FADVISE");
  }

  /* Зарезервируем память под буфер обмена, */
  /* следуя рекомендациям   */
  /* на выравнивание и размер.   */
  /* Предполагается, что значение BUFSIZ   */
  /* кратно всем нужным величинам.   */
  if ((errno = posix_memalign ((void **) &pbuf, 
      BUFSIZ, BUFSIZ)) != 0) {
    perror ("POSIX_MEMALIGN");
    return (errno);
  }

  /* Прочитаем файл и обработаем содержащиеся в нем данные */
  while ((nb = read (fd, pbuf, BUFSIZ)) > 0) {
    for (i = 0; i < nb; i++) {
      sum += pbuf [i];
    }
  }

  printf ("%ld\n", sum);

  free (pbuf);
  return (close (fd));
}
Листинг 7.10. Пример программы, использующей функции рекомендательных интерфейсов.

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

< Лекция 6 || Лекция 7: 12345 || Лекция 8 >