Каждому процессу ядро предоставляет специальный виртуальный каталог /dev/fd. Он содержит имена файлов вида /dev/fd/n, где n является номером, соответствующим одному из дескрипторов файла, открытого для этого процесса. К примеру, /dev/fd/0 является для процесса стандартным вводом. (Свойство каталога /dev/fd в SUSv3 не указано, но некоторые другие реализации UNIX его предоставляют.)
В некоторых системах (но не в Linux) открытие одного из файлов в каталоге /dev/fd эквивалентно дублированию соответствующего файлового дескриптора. Таким образом, следующие инструкции эквивалентны друг другу:
fd = open("/dev/fd/1", O_WRONLY);
fd = dup(1); /* Дублирование стандартного вывода */
Аргумент flags вызова open() интерпретируется, поэтому следует позаботиться об указании точно такого же режима доступа, который был использован исходным дескриптором. Указывать другие флаги, такие как O_CREAT, в данном контексте не имеет смысла (они просто игнорируются).
В Linux открытие одного из файлов в /dev/fd эквивалентно повторному открытию исходного файла. Иначе говоря, новый файловый дескриптор связан с новым описанием открытого файла (и, следовательно, имеет различные флаги состояния файла и смещение файла).
Фактически /dev/fd является символьной ссылкой на характерный для Linux каталог /proc/self/fd. Он представляет собой частный случай свойственных для Linux каталогов /proc/PID/fd, в каждом из которых хранятся символьные ссылки, соответствующие всем файлам, содержащимся процессом в открытом состоянии.
В программах файлы в каталоге /dev/fd редко используются. Наиболее часто они применяются в оболочке. Многие из доступных пользователю команд принимают в качестве аргументов имена файлов, и иногда удобно соединить эти команды с помощью конвейера, чтобы использовать стандартный ввод или вывод в качестве такого аргумента. Для этой цели некоторые программы (например, diff, ed, tar и comm) задействуют аргумент, состоящий из одиночного дефиса (-), означающего: «в качестве файла, имя которого должно быть указано в аргументах, использовать стандартный ввод или вывод (что больше соответствует)». Так, для сравнения списка файлов из ls с ранее созданным списком файлов можно набрать такую команду:
$ ls | diff — oldfilelist
У этого подхода имеются различные недостатки. Во-первых, он требует определенной интерпретации символа дефиса в части каждой программы, и многие программы подобной интерпретации не осуществляют; они написаны для работы только с аргументами в виде имен файлов, и у них нет средств указания стандартного ввода или вывода в качестве файлов, с которыми им нужно работать. Во-вторых, некоторые программы вместо этого интерпретируют одиночный дефис в качестве разделителя, обозначающего конец ключей командной строки.
Использование /dev/fd устраняет эти трудности, позволяя указывать стандартный ввод, вывод и ошибку в виде аргументов, обозначающих имя файла для любой программы, которой они требуются. Поэтому предыдущую команду оболочки можно переписать в таком виде:
$ ls | diff /dev/fd/0 oldfilelist
Для удобства в качестве символьных ссылок на /dev/fd/0, /dev/fd/1 и /dev/fd/2 соответственно предоставляются имена /dev/stdin, /dev/stdout и /dev/stderr.
Некоторые программы нуждаются в создании временных файлов, используемых только при выполнении программы, а при завершении программы такие файлы должны быть удалены. Например, временные файлы создаются в ходе компиляции многими компиляторами. Для этих целей в GNU-библиотеке языка C предоставляется несколько библиотечных функций. Здесь будут рассмотрены две такие функции: mkstemp() и tmpfile().
Функция mkstemp() создает уникальные имена файлов на основе шаблона, предоставляемого вызывающим процессом, и открывает файл, возвращая файловый дескриптор, который может быть использован с системными вызовами ввода-вывода.
#include
int mkstemp(char *
При успешном завершении возвращает новый файловый дескриптор, а при ошибке выдает –1
Аргумент template принимает форму путевого имени, последними шестью символами которого должны быть XXXXXX. Эти шесть символов заменяются строкой, придающей имени уникальность, и измененная строка возвращается через аргумент template. Поскольку template изменен, он должен указываться как массив символов, а не как строковая константа.
Функция mkstemp() создает файл с правами на чтение и запись для владельца файла (и без прав для других пользователей) и открывает его с флагом O_EXCL, гарантируя вызывающему процессу эксклюзивный доступ к файлу.
Обычно временный файл отсоединяется (удаляется) вскоре после своего открытия, с помощью системного вызова unlink() (см. раздел 18.3). Функцией mkstemp() можно воспользоваться следующим образом:
int fd;
char template[] = "/tmp/somestringXXXXXX";
fd = mkstemp(template);
if (fd == -1)
errExit("mkstemp");
printf("Generated filename was: %s\n", template);