Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Для изменения значения umask
предназначена одноименная команда, принимающая восьмеричный аргумент. Если требуется изменить значение umask
работающего процесса, вызовите функцию umask()
.
Например, функция
umask(S_IRWXO | S_IWGPF);
и команда
% umask 027
означают, что право записи для группы а также права чтения, записи и выполнения для остальных пользователей будут всегда отниматься от прав доступа к создаваемым файлам.
#include
#include
#include
#include
#include
int main(int argc, char* argv[]) {
/* Путевое имя нового файла */
char* path = argv[1];
/* Права доступа к файлу. */
mode_t mode =
S_IRUSR | S_IWUSR| S_IRGRP | S_IWGRP | S_IROTH;
/* Создание файла. */
int fd = open(path, O_WRONLY | O_EXCL | O_CREAT, mode);
if (fd == -1) {
/* Произошла ошибка. Выводим сообщение и завершаем работу. */
perror("open");
return 1;
}
return 0;
}
Результаты работы программы будут такими:
% ./create-file testfile
% ls -l testfile
-rw-rw-r-- 1 samuel users 0 Feb 1 22:47 testfile
% ./create-file testfile
open: File exists
Обратите внимание на то, что длина файла равна нулю, так как программа не записывала в него никакие данные.
Б.1.2. Закрытие файла
По окончании работы с файлом его следует закрыть с помощью функции close()
. В ряде случаев, например в программе, показанной в листинге Б.1, нет необходимости вызывать данную функцию явно, так как ОС Linux автоматически закрывает все открытые файлы по завершении программы. Естественно, после того как файл был закрыт, обращаться к нему нельзя.
Закрытие файла вызывает разную реакцию операционной системы, в зависимости от природы файла. Например, когда закрывается сокет, происходит разрыв сетевого соединения между двумя компьютерами, взаимодействующими через сокет.
Linux ограничивает число файлов, которые могут быть открыты процессом в определенный момент времени. Дескрипторы открытых файлов занимают ресурсы ядра, поэтому желательно вовремя закрывать файлы, чтобы дескрипторы удалялись из системных таблиц. Обычно процессам назначается лимит в 1024 дескриптора. Изменить это значение позволяет системный вызов setrlimit()
(см. раздел 8.5, "Функции getrlimit() и setrlimit(): лимиты ресурсов").
Б.1.3. Запись данных
Для записи данных в файл предназначена функция write()
. Она принимает дескриптор файла, указатель на буфер данных и число записываемых байтов. Файл должен быть открыт для записи. Функция write()
работает не только с текстовыми данными, но и с произвольными байтами.
В листинге Б.2 показана программа, которая записывает в указанный файл значение текущего времени. Если файл не существует, он создается. Для получения и форматирования значения времени программа использует функции time()
, localtime()
и asctime()
.
#include
#include
#include
#include
#include
#include
#include
/* Эта строка возвращает строку, содержащую значение
текущих даты и времени. */
char* get_timestamp() {
time_t now = time(NULL);
return asctime(localtime(&now));
}
int main(int argc, char* argv[]) {
/* Файл, в который записывается метка времени. */
char* filename = argv[1];
/* Получение метки времени. */
char* timestamp = get_timestamp();
/* Открытие файла для записи. Если файл существует, он
открывается в режиме добавления; в противном случае
файл создается. */
int fd =
open(filename. O_WRONLY | O_CREAT | O_APPEND, 0666);
/* Вычисление длины строки с меткой времени. */
size_t length = strlen(timestamp);
/* Запись метки времени в файл. */
write(fd, timestamp, length);
/* Конец работы. */
close(fd);
return 0;
}
Вот как работает программа:
% ./timestamp tsfile
% cat tsfile
The Feb 1 23:25:20 2001
% ./timestamp tsfile
% cat tsfile
Thu Feb 1 23:25:20 2001
Thu Feb 1 23:25:47 2001
Обратите внимание на то, что при первом вызове программы timestamp
файл был создан, а при втором вызове — дополнен.
Функция write()
возвращает число записанных байтов или -1, если произошла ошибка. Для некоторых типов файлов чисто фактически записанных байтов может оказаться меньше требуемого. Программа должна выявлять подобные случаи и вызывать функцию write()
повторно, чтобы передать оставшуюся часть данных. Этот прием продемонстрирован в листинге Б.3. Но иногда даже таких методов недостаточно. Например, если показанная функция будет записывать данные в сокет, в нее придется добавить код проверки того, не произошел ли в ходе операции записи разрыв соединения.
/* Запись указанного числа байтов (COUNT) из буфера BUFFER
в файл FD. В случае ошибки возвращается -1,
иначе -- число записанных байтов. */
ssize_t write_all(int fd, const void* buffer, size_t count) {
size_t left_to_write = count;
while (left_to_write > 0) {
size_t written = write(fd, buffer, count);
if (written == -1)
/* Произошла ошибка, завершаем работу. */
return -1;
else
/* подсчитываем число оставшихся байтов. */
left_to_write -= written;
}
/* Нельзя записать больше, чем COUNT байтов! */
assert(left_to_write == 0);
/* Число записанных байтов равно COUNT. */
return count;
}
Б.1.4. Чтение данных
Функция, осуществляющая чтение данных из файла, называется read()
. Подобно функции write()
, она принимает дескриптор файла, указатель на буфер и счетчик числа извлекаемых байтов. Функция возвращает число прочитанных байтов или -1 в случае ошибки. Иногда читается меньше байтов, чем требовалось, если, например, в файле содержится недостаточно байтов.
В Linux-программах нередко приходится читать файлы, созданные в DOS или Windows. Важно понимать разницу между тем, как структурируются текстовые файлы в Linux и в DOS/Windows.
В Linux каждая строка текстового файла оканчивается символом новой строки. Он представляется символьной константой '\n'
, ASCII-код которой равен 10. В Windows строки разделяются двухсимвольной комбинацией символ возврата каретки (константа '\r'
, ASCII-код 13), за которым идет символ новой строки.
Некоторые текстовые редакторы Linux при отображении текстовых файлов Windows ставят в конце каждой строки обозначение ^M
— символ возврата каретки. В Emacs такие файлы отображаются правильно, но в строке режима появляется запись (DOS)
. Многие Windows-редакторы, например Notepad (Блокнот), показывают содержимое текстовых файлов Linux в виде одной длинной строки, так как предполагают наличие в конце строки символа возврата каретки.
Интервал:
Закладка: