Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
/* Просмотр списка аргументов и создание массива. */
vec_next = vec;
for (i = 0; i < argc; ++i) {
/* первый элемент -- это текст аргумента */
vec_next->iov_base = argv[i];
vec_next->iov_len = strlen(argv[i]);
++vec_next;
/* Второй элемент -- это символ новой строки, допускается,
чтобы несколько элементов массива указывали на одну и
ту же область памяти. */
vec_next->iov_base = &newline;
vec_next->iov_len = 1;
++vec_next;
}
/* Запись аргументов в файл. */
fd = open(filename, O_WRONLY | O_CREAT);
writev(fd, vec, 2 * argc);
close(fd);
free(vec);
return 0;
}
Вот пример работы программы:
% ./write-args outputfile "first arg" "second arg" "third arg"
% cat outputfile
first arg
second arg
third arg
В Linux имеется также функция readv()
, которая загружает содержимое файла в несколько несвязанных областей памяти. Как и в функции writev()
, массив структур типа iovec определяет начало и размер каждой области.
Б.4. Взаимосвязь с библиотечными функциями ввода-вывода
Выше уже говорилось о том. что функции ввода-вывода стандартной библиотеки языка С реализованы на основе низкоуровневых функций. Иногда удобнее работать с одними, иногда — с другими.
Если файл был открыт с помощью функции fopen()
, то узнать его дескриптор позволяет функция fileno()
. Она принимает аргумент типа FILE*
и возвращает соответствующий ему дескриптор. Например, можно открыть файл с помощью библиотечной функции fopen()
, но осуществить в него запись посредством функции writev()
:
FILE* stream = fopen(filename, "w");
int file_descriptor = fileno(stream);
writev(file_descriptor, vector, vector_length);
Учтите, что переменные stream
и file_descriptor
соответствуют одному и тому же открытому файлу. Если выполнить следующую функцию, дескриптор file_descriptor
станет недействительным:
fclose(stream);
Аналогичным образом следующая функция делает недействительным файловый указатель stream
:
close(file_descriptor);
Чтобы получить файловый указатель, соответствующий дескриптору, воспользуйтесь функцией fdopen()
. Ее аргументами является дескриптор и строка, определяющая режим создания файлового потока. Синтаксис строки аналогичен синтаксису второго аргумента функции fopen()
, а задаваемый режим должен быть совместим с режимом открытия файла. Например, файлу, открытому для чтения, соответствует режим r
, а файлу, открытому для записи, — режим w
. Как и в случае функции fileno()
, файловый указатель и дескриптор ссылаются на один и тот же файл, поэтому закрытие одного сделает недействительным другой.
Б.5. Другие низкоуровневые операции
Есть ряд других полезных функций для работы с файлами и каталогами.
■ Функция getcwd()
возвращает имя текущего каталога. Она принимает два аргумента — указатель на буфер и длину буфера — и копирует имя каталога в буфер.
■ Функция chdir()
делает текущим заданный каталог.
■ Функция mkdir()
создает новый каталог. Ее первым аргументом является путевое имя каталога. Второй аргумент задает права доступа к каталогу. Интерпретация этого аргумента такая же, как и третьего аргумента функции open()
. На итоговый код доступа влияет значение umask
процесса.
■ Функция rmdir()
удаляет указанный каталог.
■ Функция unlink()
удаляет файл. Ее аргументом является путевое имя файла. С помощью этой функции можно удалять и другие объекты файловой системы, например именованные каналы и файлы устройств.
В действительности функция unlink()
не обязательно удаляет содержимое файла. Как подсказывает ее имя, она удаляет из каталога ссылку на файл. Файл не будет больше фигурировать в списке содержимого каталога, но если какой-то процесс владеет открытым дескриптором этого файла, то содержимое файла не удаляется с диска. Это произойдет только тогда, когда не останется открытых дескрипторов файла. Так что если один процесс откроет файл для чтения или записи, а второй процесс в это время удалит ссылку на файл и создаст новый файл с таким же именем, первый процесс продолжит работать со старым содержимым файла. Чтобы получить доступ к новому содержимому первому процессу придется закрыть и повторно открыть файл.
■ Функция rename()
переименовывает или перемещает файл. Двумя ее аргументами являются старое и новое путевые имена. Если путевые имена ссылаются на разные каталоги, функция перемещает файл (при условии, что он остается в той же файловой системе). С помощью функции rename()
можно перемещать также каталоги и другие объекты файловой системы.
Б.6. Чтение содержимого каталога
В Linux имеются функции, предназначенные для чтения содержимого каталога. И хотя они не относятся к низкоуровневым функциям, мы все же решили их описать, так как они широко применяются в программах.
При чтении содержимого каталога необходимо придерживаться такой последовательности действий.
1. Вызовите функцию opendir()
, передав ей путевое имя требуемого каталога. Эта функция возвращает дескриптор типа DIR*
, который можно использовать для доступа к содержимому каталога. В случае ошибки возвращается NULL
.
2. Последовательно вызывайте функцию readdir()
, передавая ей дескриптор, полученный от функции opendir()
. Всякий раз функция readdir()
будет возвращать указатель на структуру типа dirent
, содержащую информацию о следующем элементе каталога. По достижении конца каталога будет получено значение NULL
. У структуры dirent
есть поле d_name
, где содержится имя элемента каталога.
3. Вызовите функцию closedir()
, передав ей имеющийся дескриптор, чтобы завершить сеанс работы с каталогом.
Для использования перечисленных функций необходимо включить в программу файлы и . Ответственность за сортировку содержимого каталога возлагается на программу.
В листинге Б.8 показана программа отображающая список содержимого каталога. Имя каталога задается в командной строке. Если этого не сделать, будет проанализирован текущий каталог. Для каждого элемента каталога отображается его тип и путевое имя. Функция get_file_type()
определяет тип объекта файловой системы с помощью функции lstat()
.
#include
#include
#include
#include
#include
#include
#include
/* Эта функция возвращает строку с описанием типа объекта
файловой системы, заданного в аргументе PATH. */
const char* get_file_type(const char* path) {
struct stat st;
lstat(path, &st);
Интервал:
Закладка: