Главная » Просмотр файлов » Керниган и Ритчи - Язык программирования Си

Керниган и Ритчи - Язык программирования Си (793773), страница 43

Файл №793773 Керниган и Ритчи - Язык программирования Си (Керниган и Ритчи - Язык программирования Си) 43 страницаКерниган и Ритчи - Язык программирования Си (793773) страница 432019-04-24СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 43)

Эта информация сосредоточена взаголовочном файле dirent.h.#define NAME_MAX 14 /* максимальная длина имени файла; *//* системно-зависимая величина */typedef struct { /* универс. структура элемента каталога: */long ino; /* номер inode */char name[NAME_MAX+1]; /* имя + завершающий '\0' */} Dirent;typedef struct { /* минимальный DIR: без буферизации и т.д. */int fd; /* файловый дескриптор каталога */Dirent d; /* элемент каталога */} DIR;DIR *opendir(char *dirname);Dirent *readdir(DIR *dfd);void closedir(DIR *dfd);Системный вызов stat получает имя файла и возвращает полную о нем информацию, содержащуюся в узлеinode, или -1 в случае ошибки.

Так,char *name;struct stat stbuf;int stat(char *, struct stat *);stat(name, &stbuf);заполняет структуру stbuf информацией из узла inode о файле с именем name. Структура, описывающаявозвращаемое функцией stat значение, находится в <sys/stat.h> и выглядит примерно так:struct stat { /* информация из inode, возвращаемая stat */dev_t st_dev; /* устройство */ino_t st_ino; /* номер inode */short st_mode; /* режимные биты */short st_nlink; /* число связей с файлом */short st_uid; /* имя пользователя-собственника */short st_gid; /* имя группы собственника */dev_t st_rdev; /* для специальных файлов */off_t st_size; /* размер файла в символах */time_t st_atime; /* время последнего использования */time_t st_mtime; /* время последней модификации */time_t st_ctime; /* время последнего изменения inode */};Большинство этих значений объясняется в комментариях.

Типы, подобные dev_t и ino_t, определены вфайле <sys/types.h>, который тоже нужно включить посредством #include.Элемент st_mode содержит набор флажков, составляющих дополнительную информацию о файле.Определения флажков также содержатся в <sys/stat.h>; нам потребуется только та его часть, котораяимеет дело с типом файла:#define#define#define#define#defineS_IFMTS_IFDIRS_IFCHRS_IFBLKS_IFREG01600000040000002000000600000100000/*/*/*/*/*тип файла */каталог */символьно-ориентированный */блочно-ориентированный */обычный */Теперь мы готовы приступить к написанию программы fsize.

Если режимные биты (st_mode), полученныеот stat, указывают, что файл не является каталогом, то можно взять его размер (st_size) и напечатать.Однако если файл — каталог, то мы должны обработать все его файлы, каждый из которых в свою очередьможет быть каталогом. Обработка каталога — процесс рекурсивный.Программа main просматривает параметры командной строки, передавая каждый аргумент функции fsize.#include#include#include#include#include#include#include<stdio.h><string.h>"syscalls.h"<fcntl.h> /* флажки чтения и записи */<sys/types.h> /* определения типов */<sys/stat.h> /* структура, возвращаемая stat */"dirent.h"void fsize(char *);/* печатает размеры файлов */main(int argc, char **argv){if (argc == 1) /* по умолчанию берется текущий каталог */fsize(".");elsewhile (--argc > 0)fsize(*++argv);return 0;}Функция fsize печатает размер файла.

Однако, если файл — каталог, она сначала вызывает dirwalk, чтобыобработать все его файлы. Обратите внимание на то, как используются имена флажков S_IFMT и S_IFDIRиз <sys/stat.h> при проверке, является ли файл каталогом. Здесь нужны скобки, поскольку приоритетоператора & ниже приоритета оператора ==.int stat(char *, struct stat *);void dirwalk(char *, void (*fcn)(char *));/* fsize: печатает размер файла "name" */void fsize(char *name){struct stat stbuf;if (stat(name, Sstbuf) == -1) {fprintf(stderr, "fsize: нет доступа к %s\n", name);return;}if ((stbuf.stjnode & S_IFMT) == S_IFDIR)dirwalk(name, fsize);printf("%81d %s\n", stbuf.st_size, name);}Функция dirwalk — это универсальная программа, применяющая некоторую функцию к каждому файлукаталога.

Она открывает каталог, с помощью цикла перебирает содержащиеся в нем файлы, применяя ккаждому из них указанную функцию, затем закрывает каталог и осуществляет возврат. Так как fsizeвызывает dirwalk на каждом каталоге, в этих двух функциях заложена косвенная рекурсия.#define MAX_PATH 1024/* dirwalk: применяет fcn ко всем файлам из dir */void dirwalk(char *dir, void (*fcn)(char *)){char name[MAX_PATH];Dirent *dp;DIR *dfd;if ((dfd = opendir(dir)) == NULL) {fprintf(stderr, "dirwalk: не могу открыть %s\n", dir);return;}while ((dp = readdir(dfd)) != NULL) {if (strcmp(dp->name, ".") == 0|| strcmp(dp->name, "..") == 0)continue; /* пропустить себя и родителя */if (strlen(dir)+strlen(dp->name)+2 > sizeof(name))fprintf (stderr, "dirwalk: слишком длинное имя %s/%s\n",dir, dp->name);else {sprintf(name, "%s/%s", dir, dp->name);(*fcn)(name);}}closedir(dfd);}Каждый вызов readdir возвращает указатель на информацию о следующем файле или NULL, если всефайлы обработаны.

Любой каталог всегда хранит в себе информацию о себе самом в файле под именем "." ио своем родителе в файле под именем ".."; их нужно пропустить, иначе программа зациклится. Обратитевнимание: код программы этого уровня не зависит от того, как форматированы каталоги. Следующий шаг —представить минимальные версии opendir, readdir и closedir для некоторой конкретной системы.Здесь приведены программы для систем Version 7 и System V UNIX.

Они используют информацию о каталоге,хранящуюся в заголовочном файле <sys/dir.h>, который выглядит следующим образом:#ifndef DIRSIZ#define DIRSIZ 14#endifstruct direct /* элемент каталога */{ino_t d_ino; /* номер inode */char d_name[DIRSIZ]; /* длинное имя не имеет '\0' */};Некоторые версии системы допускают более длинные имена и имеют более сложную структуру каталога.Тип ino_t задан с помощью typedef и описывает индекс списка узлов inode. В системе, которойпользуемся мы, этот тип есть unsigned short, но в других системах он может быть иным, поэтому еголучше определять через typedef. Полный набор "системных" типов находится в <sys/types.h>.Функция opendir открывает каталог, проверяет, является ли он действительно каталогом (в данном случаеэто делается с помощью системного вызова fstat, который аналогичен stat, но применяется кдескриптору файла), запрашивает пространство для структуры каталога и записывает информацию.int fstat(int fd, struct stat *);/* opendir: открывает каталог для вызовов readdir */DIR *opendir(char *dirname){int fd;struct stat stbuf;DIR *dp;if ((fd = open(dirname, 0_RDONLY, 0)) == -1|| fstat(fd, Sstbuf) == -1|| (stbuf.stjnode & S_IFMT) != S_IFDIR|| (dp = (DIR *) malloc(sizeof(DIR))) == NULL)return NULL;dp->fd = fd;return dp;}Функция closedir закрывает каталог и освобождает пространство./* closedir: закрывает каталог, открытый opendir */void closedir(DIR *dp){if (dp) {close(dp->fd);free(dp);}}Наконец, readdir с помощью read читает каждый элемент каталога.

Если некий элемент каталога в данныймомент не используется (соответствующий ему файл был удален), то номер узла inode у него равен нулю, иданная позиция пропускается. В противном случае номер inode и имя размещаются в статической (static)структуре, и указатель на нее выдается в качестве результата. При каждом следующем обращении новаяинформация занимает место предыдущей.#include <sys/dir.h> /* место расположения структуры каталога *//* readdir: последовательно читает элементы каталога */Dirent *readdir(DIR *dp){struct direct dirbuf; /* структура каталога на данной системе */static Dirent d; /* возвращает унифицированную структуру */while (read(dp->fd, (char *) &dirbuf, sizeof (dirbuf ))== sizeof (dirbuf)) {if (dirbuf.d_ino == 0) /* пустой элемент, не используется */continue;d.ino = dirbuf.d_ino;strncpy(d.name, dirbuf.d_name, DIRSIZ);d.name[DIRSIZ] = '\0'; /* завершающий символ '\0' */return &d;}return NULL;}Хотя программа fsize — довольно специализированная, она иллюстрирует два важных факта.

Первый:многие программы не являются "системными"; они просто используют информацию, которую хранитоперационная система. Для таких программ существенно то, что представление информации сосредоточеноисключительно в стандартных заголовочных файлах. Программы включают эти файлы, а не держатобъявления в себе. Второе наблюдение заключается в том, что при старании системно-зависимым объектамможно создать интерфейсы, которые сами не будут системно-зависимыми. Хорошие тому примеры —функции стандартной библиотеки.Упражнение 8.5. Модифицируйте fsize таким образом, чтобы можно было печатать остальнуюинформацию, содержащуюся в узле inode.8.7.

Пример. Распределитель памятиВ главе 5 был описан простой распределитель памяти, основанный на принципе стека. Версия, которую мынапишем здесь, не имеет ограничений: вызовы malloc и free могут выполняться в любом порядке;malloc делает запрос в операционную систему на выделение памяти тогда, когда она требуется. Этипрограммы иллюстрируют приемы, позволяющие получать машинно-зависимый код сравнительно машиннонезависимым способом, и, кроме того, они могут служить примером применения таких средств языка, какструктуры, объединения и typedef.Никакого ранее скомпилированного массива фиксированного размера, из которого выделяются куски памяти,не будет. Функция malloc запрашивает память у операционной системы по мере надобности.

Поскольку идругие действия программы могут вызывать запросы памяти, которые удовлетворяются независимо от этогораспределителя памяти, пространство, которым заведует malloc, не обязательно представляет собойсвязный кусок памяти. Поэтому свободная память хранится в виде списка блоков. Каждый блок содержитразмер, указатель на следующий блок и само пространство. Блоки в списке хранятся в порядке возрастанияадресов памяти, при этом последний блок (с самым большим адресом) указывает на первый.При возникновении запроса на память просматривается список свободных блоков, пока не обнаружитсядостаточно большой блок.

Характеристики

Тип файла
PDF-файл
Размер
2,25 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7021
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее