Linux программирование в примерах
Linux программирование в примерах читать книгу онлайн
В книге рассмотрены вопросы, связанные с программированием под Linux: файловый ввод/вывод, метаданные файлов, основы управления памятью, процессы и сигналы, пользователи и группы, вопросы интернационализации и локализации, сортировка, поиск и многие другие. Много внимания уделено средствам отладки, доступным под GNU Linux. Все темы иллюстрируются примерами кода, взятого из V7 UNIX и GNU. Эта книга может быть полезна любому, кто интересуется программированием под Linux.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
#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
$ <b>ch04-maxfds</b>
max fds: 1024
Дескрипторы файлов содержатся в обычных переменных
int
int fd
В обычном случае каждая программа начинает свою работу с тремя уже открытыми для нее дескрипторами файлов. Это стандартный ввод, стандартный вывод и стандартная ошибка, с дескрипторами файлов 0, 1 и 2 соответственно. (Если не было использовано перенаправление, каждый из них связан с клавиатурой и с экраном.)
При работе с системными вызовами на основе дескрипторов файлов и стандартных ввода, вывода и ошибки целые константы 0, 1 и 2 обычно используются прямо в коде. В подавляющем большинстве случаев использование таких символических констант (manifest constants) является плохой мыслью. Вы никогда не знаете, каково значение некоторой случайной целой константы и имеет ли к ней какое-нибудь отношение константа с тем же значением, использованная в другой части кода. С этой целью стандарт POSIX требует объявить следующие именованные константы (symbolic constants) в
<unistd.h>
STDIN_FILENO
STDOUT_FILENO
STDERR_FILENO
Однако, по нашему скромному мнению, использование этих макросов избыточно. Во-первых, неприятно набирать 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].
Возвращаемое open() значение является либо новым дескриптором файла, либо -1, означающим ошибку, в этом случае будет установлена
errno
flags
Таблица 4.3. Значения
flags
open()
Именованная константа | Значение | Комментарий |
---|---|---|
O_RDONLY | 0 | Открыть файл только для чтения, запись невозможны |
O_WRONLY | 1 | Открыть файл только для записи, чтение невозможно |
O_RDWR | 2 | Открыть файл для чтения и записи |
Вскоре мы увидим пример кода. Дополнительные значения
flags
Системный вызов
close()
#include <unistd.h> /* POSIX */
int close(int fd);
В случае успеха возвращается 0, при ошибке (-1). При возникновении ошибки нельзя ничего сделать, кроме сообщения о ней. Ошибки при закрытии файлов являются необычными, но не невозможными, особенно для файлов, доступ к которым осуществляется через сеть. Поэтому хорошей практикой является проверка возвращаемого значения, особенно для файлов, открытых для записи.
Если вы будете игнорировать возвращаемое значение, специально приведите его к типу
void
(void)close(fd); /* отказ от возвращаемого значения */
Легкомысленность этого совета в том, что слишком большое количество приведений к
void
printf()
void