Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
1 /* optimal_bufsize --- определение оптимального размера буфера */23 /*4 * В целях отладки усовершенствуйте это следующим образом:5 *6 * Всегда используйте stat для файла, буфер stat используется кодом7 * более высокого уровня.8 * if (AWKBUFSIZE == "exact")9 * return the file size10 * else if (AWKBUFSIZE == число)11 * всегда возвращать это число12 * else13 * if размер < default_blocksize14 * return размер15 * else16 * return default_blocksize17 * end if18 * end if19 *20 * Приходится повозиться, чтобы иметь дело с AWKBUFSIZE лишь21 * однажды, при первом вызове этой процедуры, а не при каждом22 * ее вызове. Производительность, знаете ли.23 */2425 size_t26 optimal_bufsize(fd, stb)27 int fd;28 struct stat *stb;29 {30 char *val;31 static size_t env_val = 0;32 static short first = TRUE;33 static short exact = FALSE;3435 /* обнулить все члены, на случай, если ОС их не использует. */36 memset(stb, ' ', sizeof(struct stat));3738 /* всегда использовать stat на случай, если stb используется кодом более высокого уровня */39 if (fstat(fd, stb) == -1)40 fatal("can't stat fd %d (%s)", fd, strerror(errno));4142 if (first) {43 first = FALSE;4445 if ((val = getenv("AWKBUFSIZE")) != NULL) {46 if (strcmp(val, "exact") == 0)47 exact = TRUE;48 else if (ISDIGIT(*val)) {49 for (; *val && ISDIGIT(*val); val++)50 env_val = (env_val * 10) + *val - '0';5152 return env_val;53 }54 }55 } else if (!exact && env_val > 0)56 return env_val;57 /* else58 обрабатывать дальше */5960 /*61 * System V.n, n < 4, не имеет в структуре stat размера системного62 * блока файла. Поэтому нам нужно осуществить разумную догадку.63 * Мы используем BUFSIZ из stdio, поскольку именно это имелось64 * в виду прежде всего.65 */66 #ifdef HAVE_ST_BLKSIZE67 #define DEFBLKSIZE (stb->st_blksize > 0 ? stb->st_blksize : BUFSIZ)68 #else69 #define DEFBLKSIZE BUFSIZ70 #endif7172 if (S_ISREG(stb->st_mode) /* обычный файл */73 && 0 < stb->st_size /* ненулевой размер */74 && (stb->st_size < DEFBLKSIZE /* маленький файл */75 || exact)) /* или отладка */76 return stb->st_size; /* использовать размер файла*/7778 return DEFBLKSIZE;79 }Комментарий в строках 3–23 объясняет алгоритм. Поскольку поиск переменных окружения может быть затратным и его нужно осуществить лишь однажды, функция использует для сбора соответствующих сведений в первый раз несколько статических переменных.
Строки 42–54 выполняются лишь при первом вызове функции. Строка 43 обеспечивает это условие, устанавливая в
firstfalse"exact"env_valstrtoul()Строка 55 выполняется каждый раз, кроме первого. Если было представлено числовое значение, условие будет истинным, и возвращается это значение (строка 56). В противном случае, исполнение переходит к оставшейся части функции.
Строки 60–70 определяют
DEFBLKSIZEDEGBLKSIZEМы действительно устранили проблему [174], но между тем оставили на месте новую версию
optimal_bufsize()Незначительное увеличение размера кода и его сложности более чем компенсируется возросшей гибкостью, которая есть теперь у нас для тестирования. Более того, поскольку это код изделия, пользователь в полевых условиях может с легкостью использовать эту особенность для тестирования, чтобы определить, не появилась ли сходная проблема. (До сих пор нам не приходилось просить проделать этот тест, но приятно осознавать, что мы могли бы это сделать, если бы пришлось.)