Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
329: case '\\':
330: src++;
331: if (!*src) {
332: freeJob(job);
333: fprintf(stderr, "после \\ ожидался символ\n");
334: return 1;
335: }
336: if (* src == '*' || *srс == '[' | | *src == ']'
337: || *srс == '?')
338: *buf++ = '\\';
339: /* сквозная обработка */
340: default:
341: *buf++ = *src;
Для заключения знаков универсализации в кавычки здесь был добавлен тот же самый код.
Эти две кодовые последовательности обеспечивают передачу каждого аргумента в glob()
без поиска неожиданных совпадений.
Теперь добавим функцию globLastArgument()
, которая универсализирует самый последний аргумент для дочерней программы и замещает его любым найденным совпадением.
Для облегчения управления памяти к struct childProgram
добавляется элемент globResult
типа glob_t
, используемый для хранения результатов всех операций универсализации. Кроме того, добавляется целочисленный элемент freeGlob
, не равный нулю, если freeJob()
должна освободить globResult
. Ниже показано полное описание struct childProgram
в ladsh3.c
.
35: struct childProgram {
36: pid; /* 0, если завершена */
37: char ** argv; /* имя и аргументы программы */
38: int numRedirections; /* элементы в массиве перенаправлений */
39: struct redirection Specifier * redirections; /* перенаправления ввода-вывода */
40: glob_t globResult; /* результат универсализации параметров */
41: int freeGlob; /* нужно ли освобождать globResult? */
42: };
Во время первого запуска для командной строки функция globLastArgument()
(когда argc
для текущей дочерней оболочки равно 1) инициализирует globResult
. Для остальных аргументов она пользуется преимуществом GLOB_APPEND
для добавления новых совпадений к существующим. Это избавляет от необходимости распределения собственной памяти для целей универсализации, поскольку одиночный glob_t
при необходимости автоматически расширяется.
Если globLastArgument()
не находит совпадений, символы \
с кавычками удаляются из аргумента. В противном случае все новые совпадения копируются в список аргументов, создаваемый для дочерней программы.
Ниже приведена полная реализация globLastArgument()
. Все сложные ее части относятся к управлению памятью; фактическая универсализация похожа на реализованную в программе globit.с
, которая представлена ранее в главе.
87: void globLastArgument(struct childProgram * prog, int * argcPtr,
88: int * argcAllocedPtr) {
89: int argc = *argcPtr;
90: int argcAlloced = *argcAllocedPtr;
91: int rc;
92: int flags;
93: int i;
94: char * src, * dst;
95:
96: if (argc >1) {/* cmd->globResult уже инициализирован */
97: flags = GLOB_APPEND;
98: i = prog->globResult.gl_pathc;
99: } else {
100: prog->freeGlob = 1;
101: flags = 0;
102: i = 0;
103: }
104:
105: rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);
106: if (rc == GLOB_NOSPACE) {
107: fprintf (stderr, "не хватает памяти для выполнения универсализации\n");
108: return;
109: } else if (rc == GLOB_NOMATCH ||
110: (!rc && (prog->globResult.gl_path - i) == 1 &&
111: !strcmp(prog->argv[argc - 1],
112: prog->globResult.gl_pathv[i]))) {
113: /* необходимо удалить кавычки в \, если они все еще присутствуют */
114: src = dst = prog->argv[argc - 1];
115: while (*src) {
116: if (*src ! = '\\') *dst++ = *src;
117: src++;
118: }
119: *dst = '\0';
120: } else if (!rc) {
121: argcAlloced += (prog->globResult.gl_pathc - i);
122: prog->argv = realloc(prog->argv,
123: argcAlloced * sizeof(*prog->argv));
124: memcpy(prog->argv + (argc - 1),
125: prog->globResult.gl_pathv + i,
126: sizeof(*(prog->argv)) *
127: (prog->globResult.gl_pathc - i));
128: argc += (prog->globResult.gl_pathc - i - 1);
129: }
130:
131: *argcAllocedPtr = argcAlloced;
132: *argcPtr = argc;
133: }
Последними изменениями касаются вызовов globLastArgument()
, которые должны совершаться после синтаксического разбора нового аргумента. Вызовы добавляются в двух местах: когда за пределами строки в кавычках найдены пробелы и когда вся командная строка разобрана. Оба вызова выглядят следующим образом:
globLastArgument(prog, &argc, &argvAlloced);
Полный код ladsh3.с
доступен на Web-сайте издательства, а также на сайте, посвященном книге.
14.7. Обход деревьев файловых систем
Существуют две функции, которые облегчают приложениям просмотр всех файлов каталога, включая файлы в подкаталогах. Рекурсивный просмотр всех элементов древовидной структуры (например, файловой системы) часто называется обходом(walk) дерева и он реализуется функциями ftw()
и nftw()
. nftw()
представляет собой усовершенствованную версию ftw
.
14.7.1. Использование ftw()
#include
int ftw(const char *dir, ftwFunctionPointer callback, int depth);
Функция ftw()
начинает с каталога dir
и вызывает указанную в callback
функцию для каждого файла в этом каталоге и его подкаталогах. Функция вызывается для всех типов файлов, включая символические ссылки и каталоги. Реализация ftw()
открывает каждый найденный каталог (с помощью файлового дескриптора) и для увеличения производительности не закрывает их, пока не закончит чтение всех элементов каталога. Это означает, что он использует количество файловых дескрипторов, равное количеству уровней подкаталогов. Чтобы предотвратить недостаток файловых дескрипторов в приложении, параметр depth
ограничивает количество файловых дескрипторов ftw()
, остающихся одновременно открытыми. Если этот предел достигается, производительность снижается, поскольку каталоги необходимо часто открывать и закрывать.
Функция, на которую указывает callback
, определяется следующим образом:
int ftwCallbackFunction(const char * file, const struct stat * sb, int flag);
Эта функция вызывается один раз для каждого файла в дереве каталогов, а первый параметр, file
, представляет собой имя файла, начинающееся с dir
, которое передается ftw()
. Например, если бы аргумент dir
принимал значение .
, одним из файловых имен было бы . /bashrc
. Если бы вместо этого использовалось /etc
, имя файла выглядело бы как /etc/hosts
.
Следующий аргумент обратного вызова, sb
, указывает на структуру struct stat
как на результат применения stat()
к файлу [102] Функции ftw() необходимо выполнять stat() для каждого файла для выяснения, является ли он каталогом, и передача этой информации обратному вызову во многих случаях избавляет последний от необходимости повторного выполнения stat() для файлов.
. Аргумент flag
предоставляет информацию о файле и принимает одно из следующих значений.
FTW_F |
Файл не является символической ссылкой или каталогом. |
FTW_D |
Файл является каталогом либо символической ссылкой, указывающей на каталог. |
FTW_DNR |
Файл является каталогом, полномочий на чтение которого у приложения нет (то есть его обход невозможен). |
FTW_SL |
Файл является символической ссылкой. |
FTW_NS |
Файл является объектом, к которому не удалось применить stat() . Примером может служить файл в каталоге, права на чтение которого приложение имеет (приложение может получить список файлов этого каталога), но не имеет права на выполнение (что предотвращает успешный вызов stat() применительно к файлам этого каталога). |
Когда файл является символической ссылкой, ftw()
пытается последовать за этой ссылкой и вернуть информацию о файле, на который она указывает ( ftw()
проходит один и тот же каталог несколько раз, если на него имеется несколько символических ссылок). Однако для поврежденной ссылки не определено, вернется FTW_SL
или FTW_NS
. Это хорошая причина, чтобы использовать nftw()
.
Интервал:
Закладка: