Чтение онлайн

на главную

Жанры

Linux программирование в примерах
Шрифт:

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

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

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: %d\n", 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 */

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

int open(const char *pathname, int flags, mode_t mode);

Три аргумента следующие:

const char *pathname

Строка С, представляющая имя открываемого файла.

int flags

Поразрядное ИЛИ с одной или более констант, определенных в

<fcntl.h>
. Вскоре мы их рассмотрим.

mode_t mode

Режимы доступа для создаваемого файла. Это обсуждается далее в главе, см. раздел 4.6 «Создание файлов». При открытии существующего файла опустите этот параметр [46] .

46

open
является одним из немногих варьирующих (variadic) системных вызовов — Примеч. автора.

Возвращаемое open значение является либо новым дескриптором файла, либо -1, означающим ошибку, в этом случае будет установлена

errno
. Для простого ввода/вывода аргумент
flags
должен быть одним из значений из табл. 4.3.

Таблица 4.3. Значения

flags
для
open

Именованная константа Значение Комментарий
O_RDONLY
0 Открыть файл только для чтения, запись невозможны
O_WRONLY
1 Открыть файл только для записи, чтение невозможно
O_RDWR
2 Открыть файл для чтения и записи
Поделиться:
Популярные книги

На границе империй. Том 4

INDIGO
4. Фортуна дама переменчивая
Фантастика:
космическая фантастика
6.00
рейтинг книги
На границе империй. Том 4

Имя нам Легион. Том 4

Дорничев Дмитрий
4. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 4

Барон устанавливает правила

Ренгач Евгений
6. Закон сильного
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Барон устанавливает правила

Начальник милиции. Книга 5

Дамиров Рафаэль
5. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 5

Пенсия для морского дьявола

Чиркунов Игорь
1. Первый в касте бездны
Фантастика:
попаданцы
5.29
рейтинг книги
Пенсия для морского дьявола

Низший - Инфериор. Компиляция. Книги 1-19

Михайлов Дем Алексеевич
Фантастика 2023. Компиляция
Фантастика:
боевая фантастика
5.00
рейтинг книги
Низший - Инфериор. Компиляция. Книги 1-19

Мастер 4

Чащин Валерий
4. Мастер
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Мастер 4

Студиозус

Шмаков Алексей Семенович
3. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус

Безумный Макс. Ротмистр Империи

Ланцов Михаил Алексеевич
2. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
4.67
рейтинг книги
Безумный Макс. Ротмистр Империи

Ветер перемен

Ланцов Михаил Алексеевич
5. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Ветер перемен

По дороге пряностей

Распопов Дмитрий Викторович
2. Венецианский купец
Фантастика:
фэнтези
героическая фантастика
альтернативная история
5.50
рейтинг книги
По дороге пряностей

Убивать чтобы жить 2

Бор Жорж
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 2

Решала

Иванов Дмитрий
10. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Решала

Повелитель механического легиона. Том I

Лисицин Евгений
1. Повелитель механического легиона
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Повелитель механического легиона. Том I