Kniga-Online.club
» » » » Арнольд Роббинс - Linux программирование в примерах

Арнольд Роббинс - Linux программирование в примерах

Читать бесплатно Арнольд Роббинс - Linux программирование в примерах. Жанр: Программное обеспечение издательство -, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

Многие системы предоставляют также другие значения ошибок, а в более старых системах может не быть всех перечисленных значений ошибок. Полный список следует проверить с помощью справочных страниц intro(2) и errno(2) для локальной системы.

ЗАМЕЧАНИЕ. errno следует проверять лишь после того, как возникла ошибка и до того, как сделаны дальнейшие системные вызовы. Начальное значение той переменной 0. Однако, в промежутках между ошибками ничто не изменяет ее значения, это означает, что успешный системный вызов не восстанавливает значение 0. Конечно, вы можете вручную установить ее в 0 в самом начале или когда захотите, однако это делается редко.

Сначала мы используем errno лишь для сообщений об ошибках. Для этого имеются две полезные функции. Первая — perror():

#include <stdio.h> /* ISO С */

void perror(const char *s);

Функция perror() выводит предоставленную программой строку, за которой следует двоеточие, а затем строка, описывающая значение errno:

if (some_system_call(param1, param2) < 0) {

 perror("system call failed");

 return 1;

}

Мы предпочитаем функцию strerror(), которая принимает параметр со значением ошибки и возвращает указатель на строку с описанием ошибки:

#include <string.h> /* ISO С */

char *strerror(int errnum);

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

if (some_system_call(param1, param2) < 0) {

 fprintf(stderr, "%s: %d, %d: some_system_call failed: %sn",

  argv[0], param1, param2, strerror(errno));

 return 1;

}

По всей книге вы увидите множество примеров использования обеих функций.

4.3.2. Стиль сообщения об ошибках

Для использования в сообщениях об ошибках С предоставляет несколько специальных макросов. Наиболее широкоупотребительными являются __FILE__ и __LINE__, которые разворачиваются в имя исходного файла и номер текущей строки в этом файле. В С они были доступны с самого начала. C99 определяет дополнительный предопределенный идентификатор, __func__, который представляет имя текущей функции в виде символьной строки. Макросы используются следующим образом:

if (some_system_call(param1, param2) < 0) {

 fprintf(stderr, "%s: %s (%s %d): some_system_call(%d, %d) failed: %sn",

  argv[0], __func__, __FILE__, __LINE__,

  param1, param2, strerror(errno));

 return 1;

}

Здесь сообщение об ошибке включает не только имя программы, но также и имя функции, имя исходного файла и номер строки. Полный список идентификаторов, полезных для диагностики, приведен в табл. 4.2.

Таблица 4.2. Диагностические идентификаторы C99

Идентификатор Версия С Значение __DATE__ C89 Дата компиляции в виде «Mmm nn yyyy» __FILE_ Оригинальная Имя исходного файла в виде «program.c» __LINE__ Оригинальная Номер строки исходного файла в виде 42 __TIME__ C89 Время компиляции в виде «hh:mm:ss» __func__ C99 Имя текущей функции, как если бы было объявлено const char __func__[] = "name"

Использование __FILE__ и __LINE__ было вполне обычно для ранних дней Unix, когда у большинства людей были исходные коды и они могли находить ошибки и устранять их. По мере того, как системы Unix становились все более коммерческими, использование этих идентификаторов постепенно уменьшалось, поскольку знание положения в исходном коде дает немного пользы, когда имеется лишь двоичный исполняемый файл.

Сегодня, хотя системы GNU/Linux поставляются с исходными кодами, указанный исходный код часто не устанавливается по умолчанию. Поэтому использование этих идентификаторов для сообщений об ошибках не представляет дополнительной ценности. GNU Coding Standards даже не упоминает их.

4.4. Ввод и вывод

Все операции Linux по вводу/выводу осуществляются посредством дескрипторов файлов. Данный раздел знакомит с дескрипторами файлов, описывает, как их получать и освобождать, и объясняет, как выполнять с их помощью ввод/вывод.

4.4.1. Понятие о дескрипторах файлов

Дескриптор файла является целым значением. Действительные дескрипторы файлов начинаются с 0 и растут до некоторого установленного системой предела. Эти целые фактически являются индексами таблицы открытых файлов для каждого процесса (Таблица поддерживается внутри операционной системы; она недоступна запущенным программам.) В большинстве современных систем размеры таблиц большие. Команда 'ulimit -n' печатает это значение:

$ ulimit -n

1024

Из С максимальное число открытых файлов возвращается функцией getdtablesize() (получить размер таблицы дескрипторов):

#include <unistd.h> /* Обычный */

int getdtablesize(void);

Следующая небольшая программа выводит результат работы этой функции:

/* ch04-maxfds.с --- Демонстрация getdtablesize(). */

#include <stdio.h> /* для fprintf(), stderr, BUFSIZ */

#include <unistd.h> /* для ssize_t */

int main(int argc, char **argv) {

 printf("max fds: %dn", getdtablesize());

 exit(0);

}

Неудивительно, что после компиляции и запуска эта программа выводит то же значение, что и ulimit:

$ ch04-maxfds

max fds: 1024

Дескрипторы файлов содержатся в обычных переменных int; для использования с системными вызовами ввода/вывода можно увидеть типичные объявления вида 'int fd'. Для дескрипторов файлов нет предопределенного типа.

В обычном случае каждая программа начинает свою работу с тремя уже открытыми для нее дескрипторами файлов. Это стандартный ввод, стандартный вывод и стандартная ошибка, с дескрипторами файлов 0, 1 и 2 соответственно. (Если не было использовано перенаправление, каждый из них связан с клавиатурой и с экраном.)

Очевидные символические константы. Оксюморон?

При работе с системными вызовами на основе дескрипторов файлов и стандартных ввода, вывода и ошибки целые константы 0, 1 и 2 обычно используются прямо в коде. В подавляющем большинстве случаев использование таких символических констант (manifest constants) является плохой мыслью. Вы никогда не знаете, каково значение некоторой случайной целой константы и имеет ли к ней какое-нибудь отношение константа с тем же значением, использованная в другой части кода. С этой целью стандарт POSIX требует объявить следующие именованные константы (symbolic constants) в <unistd.h>:

STDIN_FILENO  «Номер файла» для стандартного ввода: 0.

STDOUT_FILENO Номер файла для стандартного вывода: 1.

STDERR_FILENO Номер файла для стандартной ошибки: 2.

Однако, по нашему скромному мнению, использование этих макросов избыточно. Во-первых, неприятно набирать 12 или 13 символов вместо 1. Во-вторых, использование 0, 1 и 2 так стандартно и так хорошо известно, что на самом деле нет никаких оснований для путаницы в смысле этих конкретных символических констант.

С другой стороны, использование этих констант не оставляет сомнений в намерениях программиста. Сравните это утверждение:

int fd = 0;

Инициализируется ли fd значением стандартного ввода, или же программист благоразумно инициализирует свои переменные подходящим значением? Вы не можете этого сказать.

Один из подходов (рекомендованный Джеффом Колье (Geoff Collyer)) заключается в использовании следующего определения enum:

enum { Stdin, Stdout, Stderr };

Затем эти константы можно использовать вместо 0, 1 и 2. Их легко читать и печатать.

4.4.2. Открытие и закрытие файлов

Новые дескрипторы файлов получают (наряду с другими источниками) в результате системного вызова open(). Этот системный вызов открывает файл для чтения или записи и возвращает новый дескриптор файла для последующих операций с этим файлом. Мы видели объявление раньше:

#include <sys/types.h> /* POSIX */

Перейти на страницу:

Арнольд Роббинс читать все книги автора по порядку

Арнольд Роббинс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


Linux программирование в примерах отзывы

Отзывы читателей о книге Linux программирование в примерах, автор: Арнольд Роббинс. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*