Dos fn 45h дублировать описатель файла dup


Dos fn 45h: дублировать описатель файла dup

После успешного выполнения старый и новый файловые дескрипторы являются взаимозаменяемыми. Они указывают на одно и то же открытое файловое описание (смотрите open(2)) и поэтому имеют общее файловое смещение и флаги состояния файла; например, если файловое смещение изменить с помощью lseek(2) через один из файловых дескрипторов, то смещение изменится и для другого.

Эти два файловых дескриптора имеют различные флаги дескриптора файла (флаг close-on-exec). Флаг close-on-exec (FD_CLOEXEC; см. fcntl(2)) у копии дескриптора сбрасывается.

Шаги по закрытию и повторному использованию файлового дескриптора newfd выполняются атомарно. Это важно, так как попытка реализовать подобное с помощью close(2) и dup() привело бы к состязательности, в силу чего newfd мог быть задействован повторно между этими двумя шагами. Такое повторное использование может произойти, из-за прерывания основной программы обработчиком сигналов, который выделяет файловый дескриптор, или из-за параллельной нити, выделяющей файловый дескриптор.

Также заметим следующее:

* Если oldfd является некорректным файловым дескриптором, то вызов завершается с ошибкой, а newfd не закрывается. * Если oldfd является корректным файловым дескриптором, а номер newfd совпадает с oldfd, то dup2() не делает ничего и возвращает значение newfd.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

ОШИБКИ

ВЕРСИИ

СООТВЕТСТВИЕ СТАНДАРТАМ

dup3() есть только в Linux.

ЗАМЕЧАНИЯ

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

работа с файлами

16.12.2013, 21:59

работа с файлами
Всем привет.Не открывается файл по какой то причине,в чем проблема подскажите пожалуйста. .model.

Работа с файлами
Работа с файлами: прочитать данные из файла и получить сумму всех элементов. Имя файла задать из.

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

Работа с файлами
Дорогие товарищи! помогите чем сможете,никак не могу осилить файлы в ассемблере. А сдать.

Работа с файлами
Помогите добавить в программу работу с файлами. Сама программа вводит матрицу и ищет в ней.

20.12.2013, 17:23 [ТС] 2 20.12.2013, 17:37 3

Вы пытаетесь COM-файл скомпилировать как EXE. У вас TASM? Выполняйте tlink /t имя_файла.obj

И если это действительно TASM, надо бы SIZEOF заменить на SIZE.

У меня компилируется и собирается без проблем (TASM / MASM).

20.12.2013, 17:54 [ТС] 4

Вы пытаетесь COM-файл скомпилировать как EXE. У вас TASM? Выполняйте tlink /t имя_файла.obj

И если это действительно TASM, надо бы SIZEOF заменить на SIZE.

У меня компилируется и собирается без проблем (TASM / MASM).

Закрывает исходный дескриптор. Это происходит независимо от какого-либо возвращенного состояния ошибки.

DUPLICATE_SAME_ACCESS

Игнорирует параметр dwDesiredAccess . Продублированный дескриптор имеет тот же самый доступ, что и исходный дескриптор.

Если функция завершается успешно, величина возвращаемого значения — не ноль.

Если функция завершается с ошибкой, величина возвращаемого значения — ноль. Чтобы получать расширенные данные об ошибках, вызовите GetLastError .

Функция DuplicateHandle может вызываться или исходным процессом, или целевым процессом. Она может также быть вызвана, где исходный и целевой процесс — одно и то же. Например, процесс может использовать DuplicateHandle , чтобы создать ненаследуемый дубликат наследуемого дескриптора, или дескриптора с другими правами доступа, чем исходный дескриптор.

Процесс дублирования использует функцию GetCurrentProcess , чтобы получить свой собственный дескриптор. Чтобы получить другой дескриптор процесса, может быть необходимо использовать некоторую форму межпроцессорного взаимодействия (например, именованный канал или совместно используемую память), чтобы сообщить идентификатор процесса процессу дублирования. Этот идентификатор затем используется в функции OpenProcess , чтобы открыть дескриптор.

Если процесс, который вызывает функцию DuplicateHandle — не целевой процесс, процесс дублирования должен использовать межпроцессорную связь, чтобы передать значение продублированного дескриптора целевому процессу.

DuplicateHandle может дублировать дескрипторы ниже перечисленных типов объектов.

Объект

Описание

Признак доступа (Access token)

Дескриптор возвращается функцией CreateRestrictedToken , DuplicateToken , DuplicateTokenEx , OpenProcessToken , или OpenThreadToken .

Устройство связи (Communications device)

Дескриптор возвращается функцией CreateFile .

Консольный ввод данных (Console input)

Дескриптор возвращается функцией CreateFile , когда установлен CONIN$, или функцией GetStdHandle , когда установлен флажок STD_INPUT_HANDLE . Консольные дескрипторы могут быть дублированы для использования только в том же самом процессе.

Экранный буфер консоли (Console screen buffer)

Дескриптор возвращается функцией CreateFile , когда установлен CONOUT$ , или функцией GetStdHandle , когда установлен флажок STD_OUTPUT_HANDLE . Консольные дескрипторы могут быть продублированы для использования только в том же самом процессе.

Рабочий стол (Desktop)

Дескриптор возвращается функцией GetThreadDesktop .

Каталог (Directory)

Дескриптор возвращается функцией CreateDirectory .

Событие (Event)

Дескриптор возвращается функцией CreateEvent или OpenEvent .

Файл (File)

Дескриптор возвращается функцией CreateFile .

Файл, отображаемый в память (File mapping)

Дескриптор возвращается функцией CreateFileMapping .

Задание (Job)

Дескриптор возвращается функцией CreateJobObject .

Почтовый ящик в ядре системы (Mailslot)

Дескриптор возвращается функцией CreateMailslot .

Мьютекс (Mutex)

Дескриптор возвращается функцией CreateMutex или OpenMutex .

Канал (Pipe)

Дескриптор именованного канала возвращается функцией CreateNamedPipe или CreateFile . Дескриптор анонимного канала возвращается функцией CreatePipe .

Процесс (Process)

Ключ системного реестра (Registry key)

Дескриптор возвращается функцией CreateSemaphore или OpenSemaphore .

Сокет (Socket)

Дескриптор возвращается функцией socket или accept .

Поток (Thread)

Таймер (Timer)

Дескриптор возвращается функцией CreateWaitableTimer или OpenWaitableTimer .

Оконный режим терминала (Window station)

Дескриптор возвращается функцией GetProcessWindowStation .

Обратите внимание! что функция DuplicateHandle не должна использоваться для дублирования дескрипторов портов завершения ввода-вывода. В этом случае, не возвращается никакой ошибки, но продублированный дескриптор не может быть использован.

В дополнение к флажку STANDARD_RIGHTS_REQUIRED , нижеследующие права доступа могут быть определены в параметре dwDesiredAccess для других типов объекта:

Защита рабочего стола и права доступа

Защита файла и каталога и права доступа

Защита файла, отображаемого в памяти и права доступа

Защита объекта задания и права доступа

Защита процесса и права доступа

Защита объекта синхронизации и права доступа

Защита потока и права доступа

Защита оконного режима терминала и права доступа

В некоторых случаях, новый дескриптор может иметь большее количество прав доступа, чем исходный дескриптор. Однако в других случаях, DuplicateHandle не может создать дескриптор с большим количеством прав доступа, чем оригинал. Например, дескриптор файла, созданный с правом доступа GENERIC_READ не может быть продублирован так, чтобы он имел, и право доступа GENERIC_READ и GENERIC_WRITE .

Системное программное обеспечение: Учебное пособие

Для того, чтобы оценить ресурс, необходимо авторизоваться.

Настоящее учебное пособие предназначено для подготовки студентов различных вычислительных специальностей, изучающих работу в среде MS-DOS. Для специальности 2201 эта работа может использоваться в курсах «Системное программное обеспечение», «Проектирование микропроцессорных систем», «Организация ввода-вывода». В пособии описано семейство микропроцессоров х86 с точки зрения программиста, рассмотрены регистры процессора, способы адресации и формирования исполнительного адреса. Даны основы программирования на ассемблере, приведены примеры программ, использующих ресурсы MS-DOS. Рассмотрены способы написания резидентных программ и драйверов. Рассмотрены соответствующие примеры.

Основы программирования в Linux (40 стр.)

Системные вызовы dup позволяют дублировать дескриптор файла, предоставляя два или несколько разных дескрипторов, обращающихся к одному и тому же файлу. Эта возможность может применяться для чтения и записи в разные части файла. Системный вызов dup дублирует файловый дескриптор fildes и возвращает новый дескриптор. Системный вызов dup2 умело копирует один дескриптор файла в другой, задавая дескриптор, применяемый для копии.

Далее приведена синтаксическая запись для вызовов.

#include

int dup(int fildes);

int dup2(int fildes, int fildes2);

Эти вызовы могут оказаться полезными в случае нескольких процессов, взаимодействующих через именованные каналы. Более глубоко мы рассмотрим системные вызовы dup в главе 13.

Стандартная библиотека ввода/вывода

Стандартная библиотека ввода/вывода (stdio) и ее заголовочный файл stdio.h предоставляют универсальный интерфейс для системных вызовов ввода/вывода нижнего уровня. Библиотека, теперь часть языка С стандарта ANSI, в отличие от системных вызовов, с которыми вы встречались ранее, включает много сложных функций для форматирования вывода и просмотра ввода. Она также обеспечивает необходимые условия буферизации для устройств.

Во многих случаях эта библиотека используется так же, как низкоуровневые дескрипторы файлов. Вы должны открыть файл для установления пути доступа. Это действие возвращает значение, применяемое как параметр в других функциях библиотеки ввода/вывода. Эквивалент низкоуровневого дескриптора файла называется потоком и реализуется как указатель на структуру FILE* .

Не путайте эти потоки файлов с потоками ввода/вывода в языке С++ и механизмом STREAMS, описывающим взаимодействие процессов и введенным в системе AT&T UNIX System V Release 3, который не рассматривается в данной книге. Для получения дополнительной информации о средствах STREAMS обратитесь к спецификации X/Open (по адресу http://www.opengroup.org) и руководству по программированию AT&T STREAMS Programming Guide, поставляемому с системой System V.

Три файловых потока открываются автоматически при старте программы. К ним относятся stdin, stdout и stderr. Эти потоки объявлены в файле stdio.h и представляют вывод, ввод и стандартный поток ошибок, которым соответствуют низкоуровневые файловые дескрипторы 0, 1 и 2.

В данном разделе мы рассмотрим следующие функции:

□ fgetc , getc , getchar;

□ fputc , putc , putchar ;

□ printf , fprintf и sprintf ;

□ scanf , fscanf и sscanf ;

fopen

Библиотечная функция f o pen — это аналог низкоуровневого системного вызова open . Она используется в основном для файлов и терминального, ввода и вывода. Там, где нужно явное управление устройствами, больше подойдут системные вызовы, поскольку они устраняют потенциальные нежелательные побочные эффекты применения библиотек, например, в случае буферизации ввода/вывода.

Далее приведена синтаксическая запись функции:

#include

FILE *fopen(const char *filename, const char *mode);

Функция fopen открывает файл, заданный в параметре filename , и ассоциирует с ним поток. Параметр mode описывает, как файл должен быть открыт. Он задается одной из следующих строк:

□ » r » или » rb » — открыть только для чтения;

□ » w » или » wb » — открыть для записи, укоротить до нулевой длины;

□ » а » или » ab » — открыть для записи, дописывать в конец файла;

□ » r+ » или » rb+ » или » r+b » — открыть для изменения (чтение и запись);

□ » w+ » или » wb+ » или » w+b » — открыть для изменения, укоротить до нулевой длины;

□ » a+ » или » ab+ » или » а+b » — открыть для изменения, дописывать в конец файла. Символ b означает, что файл бинарный, а не текстовый.

В отличие от MS-DOS, системы UNIX и Linux не делают различий между текстовыми и бинарными файлами. UNIX и Linux обрабатывают их одинаково с эффективностью обработки бинарных файлов. Важно также учесть, что параметр mode должен быть строкой, а не символом. Всегда применяйте двойные кавычки, а не апострофы.

В случае успешного завершения функция fopen возвращает ненулевой указатель на структуру FILE* . В случае сбоя она вернет значение NULL , определенное в файле stdio.h.

Количество доступных потоков ограничено, как и число дескрипторов файлов. Реальное предельное значение содержится в определенной в файле stdio.h константе FOPEN_MAX и всегда не менее 8, а в ОС Linux обычно 16.

fread

Библиотечная функция fread применяется для чтения данных из файлового потока. Данные считываются из потока stream в буфер данных, заданный в параметре ptr . Функции fread и fwrite имеют дело с записями данных. Записи описываются размером size и количеством передаваемых записей nitems . Функция возвращает количество записей (а не байтов), успешно считанных в буфер данных. При достижении конца файла может быть возвращено меньше записей, чем nitems , вплоть до нуля.

Далее приведена синтаксическая запись функции:

#include

size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

Как и в других функциях стандартного ввода/вывода, записывающих данные в буфер, выделять место для данных и проверять ошибки должен программист. См. также функции ferror и feof далее в этой главе.

fwrite

Интерфейс библиотечной функции fwrite аналогичен интерфейсу функции fread . Она принимает записи данных из заданного буфера данных и записывает их в поток вывода. Функция возвращает количество успешно записанных записей.

Далее приведена синтаксическая запись функции:

#include

size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);

Имейте в виду, что функции fread и fwrite не рекомендуется применять со структурированными данными. Частично проблема заключается в том, что файлы, записанные функцией fwrite, могут быть непереносимыми между машинами с разной архитектурой.

fclose

Библиотечная функция fclose закрывает заданный поток stream, заставляя записать все незаписанные данные. Важно применять функцию fclose , поскольку библиотека stdio будет использовать буфер для данных. Если программе нужна уверенность в том, что все данные записаны, следует вызвать fclose . Имейте в виду, что функция fclose вызывается автоматически для всех файловых потоков, которые все еще открыты к моменту нормального завершения программы, но при этом у вас, конечно же, не будет возможности проверить ошибки, о которых сообщает fclose .

Далее приведена синтаксическая запись функции:

#include

int fclose(FILE* stream);

Dup2/dup — зачем мне дублировать файловый дескриптор?

Я пытаюсь понять использование dup2 и dup .

На странице man:

Зачем мне этот системный вызов? в чем заключается дублирование файлового дескриптора?

Если у меня есть файловый дескриптор, зачем мне его копировать?

Буду признателен, если бы вы могли объяснить и дать мне пример, где требуется dup2 / dup .

Системный вызов dup дублирует существующий файловый дескриптор, возвращая новый, который относится к одному и тому же базовому объекту ввода-вывода.

Dup позволяет оболочкам реализовать такие команды:

2 > & 1 сообщает оболочке предоставить команду файловому дескриптору 2, который является дубликатом дескриптора 1. (то есть stderr и stdout указывают на тот же fd).
Теперь сообщение об ошибке для вызова ls на несуществующий файл и правильный вывод ls в существующем файле отображаются в файле tmp1.

Следующий пример кода запускает программу wc со стандартным подключением к считываемому концу трубы.

Ребенок дублирует конец чтения на дескриптор файла 0, закрывает файл de скрипты в p и execs wc. Когда wc читает со своего стандартного ввода, он считывает из трубы.
Это то, как трубы реализованы с использованием dup, так что, используя дуп, вы используете канал для сборки чего-то еще, что красота системных вызовов вы строите одну вещь за другой, используя уже существующие инструменты, этот инструмент был построен с использованием что-то еще. В конце системные вызовы — это самые основные инструменты, которые вы получаете в ядре

Dos fn 45h: дублировать описатель файла dup

Функция DuplicateHandle делает копию дескриптора объекта. Продублированный дескриптор относится к тому же самому объекту, что и исходный дескриптор. Поэтому, любое изменение объекта отражается через оба дескриптора. Например, дескриптор файла, зарегистрированный для текущего файла, является всегда одним и тем же для обоих дескрипторов.

[in] Дескриптор процесса, дескриптор которого дублируется.

Windows NT /2000/XP: дескриптор должен иметь право доступа PROCESS_DUP_HANDLE . Для получения дополнительной информации, см. статью Защита процесса и права доступа.

[in] Дескриптор, который дублируется. Это открытый дескриптор объекта, который является правильным применительно к исходному процессу. Перечень объектов, дескрипторы которых могут быть продублированы, см. нижеследующем разделе Замечаний.

[in] Дескриптор процесса, который должен получить продублированный дескриптор. Дескриптор должен иметь право доступа PROCESS_DUP_HANDLE .

[out] Указатель на переменную, которая получает значение продублированного дескриптора. Это значение дескриптора правильно применительно к целевому процессу.

Если параметр lpTargetHandle имеет значение ПУСТО (NULL), функция делает копию дескриптора, но не возвращает значение продублированного дескриптора вызывающей программе. Это поведение существует только для совместимости вниз с предшествующими версиями этой функции. Вы не должны использовать эту функцию, поскольку будете терять системные ресурсы до тех пор, пока не целевой процесс не закончит свою работу.

[in] Доступ, требуемый для нового дескриптора. Перечень флажков, которые могут быть установлены для каждого типа объекта, см. в нижеследующем разделе Замечаний.

Этот параметр игнорируется, если параметр dwOptions устанавливает флажок DUPLICATE_SAME_ACCESS . Иначе, флажки, которые могут быть установлены, зависят от типа объекта, дескриптор которого должен быть продублирован.

[in] Указывает, является ли дескриптор наследуемым. Если он — ИСТИНА (TRUE), продублированный дескриптор может быть унаследован новыми процессами, созданными целевым процессом. Если он — ЛОЖЬ (FALSE), новый дескриптор не может быть унаследован.

[in] Необязательные действия. Этот параметр может быть нулевой, или любой комбинацией следующих значений.

Значение

Закрывает исходный дескриптор. Это происходит независимо от какого-либо возвращенного состояния ошибки.

DUPLICATE_SAME_ACCESS

Игнорирует параметр dwDesiredAccess . Продублированный дескриптор имеет тот же самый доступ, что и исходный дескриптор.

Если функция завершается успешно, величина возвращаемого значения — не ноль.

Если функция завершается с ошибкой, величина возвращаемого значения — ноль. Чтобы получать расширенные данные об ошибках, вызовите GetLastError .

Функция DuplicateHandle может вызываться или исходным процессом, или целевым процессом. Она может также быть вызвана, где исходный и целевой процесс — одно и то же. Например, процесс может использовать DuplicateHandle , чтобы создать ненаследуемый дубликат наследуемого дескриптора, или дескриптора с другими правами доступа, чем исходный дескриптор.

Процесс дублирования использует функцию GetCurrentProcess , чтобы получить свой собственный дескриптор. Чтобы получить другой дескриптор процесса, может быть необходимо использовать некоторую форму межпроцессорного взаимодействия (например, именованный канал или совместно используемую память), чтобы сообщить идентификатор процесса процессу дублирования. Этот идентификатор затем используется в функции OpenProcess , чтобы открыть дескриптор.

Если процесс, который вызывает функцию DuplicateHandle — не целевой процесс, процесс дублирования должен использовать межпроцессорную связь, чтобы передать значение продублированного дескриптора целевому процессу.

DuplicateHandle может дублировать дескрипторы ниже перечисленных типов объектов.

Объект

Описание

Признак доступа (Access token)

Дескриптор возвращается функцией CreateRestrictedToken , DuplicateToken , DuplicateTokenEx , OpenProcessToken , или OpenThreadToken .

Устройство связи (Communications device)

Дескриптор возвращается функцией CreateFile .

Консольный ввод данных (Console input)

Дескриптор возвращается функцией CreateFile , когда установлен CONIN$, или функцией GetStdHandle , когда установлен флажок STD_INPUT_HANDLE . Консольные дескрипторы могут быть дублированы для использования только в том же самом процессе.

Экранный буфер консоли (Console screen buffer)

Дескриптор возвращается функцией CreateFile , когда установлен CONOUT$ , или функцией GetStdHandle , когда установлен флажок STD_OUTPUT_HANDLE . Консольные дескрипторы могут быть продублированы для использования только в том же самом процессе.

Рабочий стол (Desktop)

Дескриптор возвращается функцией GetThreadDesktop .

Каталог (Directory)

Дескриптор возвращается функцией CreateDirectory .

Событие (Event)

Дескриптор возвращается функцией CreateEvent или OpenEvent .

Файл (File)

Дескриптор возвращается функцией CreateFile .

Файл, отображаемый в память (File mapping)

Дескриптор возвращается функцией CreateFileMapping .

Задание (Job)

Дескриптор возвращается функцией CreateJobObject .

Почтовый ящик в ядре системы (Mailslot)

Дескриптор возвращается функцией CreateMailslot .

Мьютекс (Mutex)

Дескриптор возвращается функцией CreateMutex или OpenMutex .

Канал (Pipe)

Дескриптор именованного канала возвращается функцией CreateNamedPipe или CreateFile . Дескриптор анонимного канала возвращается функцией CreatePipe .

Процесс (Process)

Ключ системного реестра (Registry key)

Дескриптор возвращается функцией CreateSemaphore или OpenSemaphore .

Сокет (Socket)

Дескриптор возвращается функцией socket или accept .

Поток (Thread)

Таймер (Timer)

Дескриптор возвращается функцией CreateWaitableTimer или OpenWaitableTimer .

Оконный режим терминала (Window station)

Дескриптор возвращается функцией GetProcessWindowStation .

Обратите внимание! что функция DuplicateHandle не должна использоваться для дублирования дескрипторов портов завершения ввода-вывода. В этом случае, не возвращается никакой ошибки, но продублированный дескриптор не может быть использован.

В дополнение к флажку STANDARD_RIGHTS_REQUIRED , нижеследующие права доступа могут быть определены в параметре dwDesiredAccess для других типов объекта:

Защита рабочего стола и права доступа

Защита файла и каталога и права доступа

Защита файла, отображаемого в памяти и права доступа

Защита объекта задания и права доступа

Защита процесса и права доступа

Защита объекта синхронизации и права доступа

Защита потока и права доступа

Защита оконного режима терминала и права доступа

В некоторых случаях, новый дескриптор может иметь большее количество прав доступа, чем исходный дескриптор. Однако в других случаях, DuplicateHandle не может создать дескриптор с большим количеством прав доступа, чем оригинал. Например, дескриптор файла, созданный с правом доступа GENERIC_READ не может быть продублирован так, чтобы он имел, и право доступа GENERIC_READ и GENERIC_WRITE .

Основы программирования в Linux (40 стр.)

Системные вызовы dup позволяют дублировать дескриптор файла, предоставляя два или несколько разных дескрипторов, обращающихся к одному и тому же файлу. Эта возможность может применяться для чтения и записи в разные части файла. Системный вызов dup дублирует файловый дескриптор fildes и возвращает новый дескриптор. Системный вызов dup2 умело копирует один дескриптор файла в другой, задавая дескриптор, применяемый для копии.

Далее приведена синтаксическая запись для вызовов.

#include

int dup(int fildes);

int dup2(int fildes, int fildes2);

Эти вызовы могут оказаться полезными в случае нескольких процессов, взаимодействующих через именованные каналы. Более глубоко мы рассмотрим системные вызовы dup в главе 13.

Стандартная библиотека ввода/вывода

Стандартная библиотека ввода/вывода (stdio) и ее заголовочный файл stdio.h предоставляют универсальный интерфейс для системных вызовов ввода/вывода нижнего уровня. Библиотека, теперь часть языка С стандарта ANSI, в отличие от системных вызовов, с которыми вы встречались ранее, включает много сложных функций для форматирования вывода и просмотра ввода. Она также обеспечивает необходимые условия буферизации для устройств.

Во многих случаях эта библиотека используется так же, как низкоуровневые дескрипторы файлов. Вы должны открыть файл для установления пути доступа. Это действие возвращает значение, применяемое как параметр в других функциях библиотеки ввода/вывода. Эквивалент низкоуровневого дескриптора файла называется потоком и реализуется как указатель на структуру FILE* .

Не путайте эти потоки файлов с потоками ввода/вывода в языке С++ и механизмом STREAMS, описывающим взаимодействие процессов и введенным в системе AT&T UNIX System V Release 3, который не рассматривается в данной книге. Для получения дополнительной информации о средствах STREAMS обратитесь к спецификации X/Open (по адресу http://www.opengroup.org) и руководству по программированию AT&T STREAMS Programming Guide, поставляемому с системой System V.

Три файловых потока открываются автоматически при старте программы. К ним относятся stdin, stdout и stderr. Эти потоки объявлены в файле stdio.h и представляют вывод, ввод и стандартный поток ошибок, которым соответствуют низкоуровневые файловые дескрипторы 0, 1 и 2.

В данном разделе мы рассмотрим следующие функции:

□ fgetc , getc , getchar;

□ fputc , putc , putchar ;

□ printf , fprintf и sprintf ;

□ scanf , fscanf и sscanf ;

fopen

Библиотечная функция f o pen — это аналог низкоуровневого системного вызова open . Она используется в основном для файлов и терминального, ввода и вывода. Там, где нужно явное управление устройствами, больше подойдут системные вызовы, поскольку они устраняют потенциальные нежелательные побочные эффекты применения библиотек, например, в случае буферизации ввода/вывода.

Далее приведена синтаксическая запись функции:

#include

FILE *fopen(const char *filename, const char *mode);

Функция fopen открывает файл, заданный в параметре filename , и ассоциирует с ним поток. Параметр mode описывает, как файл должен быть открыт. Он задается одной из следующих строк:

□ » r » или » rb » — открыть только для чтения;

□ » w » или » wb » — открыть для записи, укоротить до нулевой длины;

□ » а » или » ab » — открыть для записи, дописывать в конец файла;

□ » r+ » или » rb+ » или » r+b » — открыть для изменения (чтение и запись);

□ » w+ » или » wb+ » или » w+b » — открыть для изменения, укоротить до нулевой длины;

□ » a+ » или » ab+ » или » а+b » — открыть для изменения, дописывать в конец файла. Символ b означает, что файл бинарный, а не текстовый.

В отличие от MS-DOS, системы UNIX и Linux не делают различий между текстовыми и бинарными файлами. UNIX и Linux обрабатывают их одинаково с эффективностью обработки бинарных файлов. Важно также учесть, что параметр mode должен быть строкой, а не символом. Всегда применяйте двойные кавычки, а не апострофы.

В случае успешного завершения функция fopen возвращает ненулевой указатель на структуру FILE* . В случае сбоя она вернет значение NULL , определенное в файле stdio.h.

Количество доступных потоков ограничено, как и число дескрипторов файлов. Реальное предельное значение содержится в определенной в файле stdio.h константе FOPEN_MAX и всегда не менее 8, а в ОС Linux обычно 16.

fread

Библиотечная функция fread применяется для чтения данных из файлового потока. Данные считываются из потока stream в буфер данных, заданный в параметре ptr . Функции fread и fwrite имеют дело с записями данных. Записи описываются размером size и количеством передаваемых записей nitems . Функция возвращает количество записей (а не байтов), успешно считанных в буфер данных. При достижении конца файла может быть возвращено меньше записей, чем nitems , вплоть до нуля.

Далее приведена синтаксическая запись функции:

#include

size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

Как и в других функциях стандартного ввода/вывода, записывающих данные в буфер, выделять место для данных и проверять ошибки должен программист. См. также функции ferror и feof далее в этой главе.

fwrite

Интерфейс библиотечной функции fwrite аналогичен интерфейсу функции fread . Она принимает записи данных из заданного буфера данных и записывает их в поток вывода. Функция возвращает количество успешно записанных записей.

Далее приведена синтаксическая запись функции:

#include

size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);

Имейте в виду, что функции fread и fwrite не рекомендуется применять со структурированными данными. Частично проблема заключается в том, что файлы, записанные функцией fwrite, могут быть непереносимыми между машинами с разной архитектурой.

fclose

Библиотечная функция fclose закрывает заданный поток stream, заставляя записать все незаписанные данные. Важно применять функцию fclose , поскольку библиотека stdio будет использовать буфер для данных. Если программе нужна уверенность в том, что все данные записаны, следует вызвать fclose . Имейте в виду, что функция fclose вызывается автоматически для всех файловых потоков, которые все еще открыты к моменту нормального завершения программы, но при этом у вас, конечно же, не будет возможности проверить ошибки, о которых сообщает fclose .

Далее приведена синтаксическая запись функции:

#include

int fclose(FILE* stream);

Илон Маск рекомендует:  Сравнение методов
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
20.12.2013, 17:54
20.12.2013, 18:01 5

Ну, почти правильно Ещё чуть-чуть и соберём.

Вы написали tlink file4.obj, а нужно было tlink /t file4.obj.

20.12.2013, 18:12 [ТС] 6

Ну, почти правильно Ещё чуть-чуть и соберём.

Вы написали tlink file4.obj, а нужно было tlink /t file4.obj.

20.12.2013, 18:15 7

А вы не пишите EXE. Должен получиться .COM, а не .EXE.

EXE остался от предыдущей (некорректной) сборки, когда вы не использовали ключ /t, можете этот файл вообще удалить.

20.12.2013, 18:43 [ТС] 8

А вы не пишите EXE. Должен получиться .COM, а не .EXE.

EXE остался от предыдущей (некорректной) сборки, когда вы не использовали ключ /t, можете этот файл вообще удалить.

20.12.2013, 18:55 9

DOS Fn 0aH: ввод строки в буфер :: int 21h

Вход

  • AH = 0aH
  • DS:DX = адрес входного буфера (смотри ниже)

Выход

  • нет = буфер содержит ввод, заканчивающийся символом CR (ASCII 0dH)

Описание:

при входе буфер по адресу DS:DX должен быть оформлен так:

символы считываются со стандартного ввода вплоть до CR (ASCII 0dH) или до достижения длины MAX-1. если достигнут MAX-1, включается консольный звонок для каждого очередного символа, пока не будет введен возврат каретки CR (нажатие Enter).

Второй байт буфера заполняется действительной длиной введенной строки, не считая завершающего CR. последний символ в буфере — всегда CR (который не засчитан в байте длины). символы в буфере (включая LEN) в момент вызова используются как «шаблон». В процессе ввода действительны обычные клавиши редакти рования: Esc выдает «\» и начинает с начала, F3 выдает буфер до конца шаблона, F5 выдает «@» и сохраняет текущую строку как шаблон, и т.д. большинство расширенных кодов ASCII игнорируются. при распознавании Ctrl-Break выполняется прерывание INT 23H (буфер остается неизменным).

Asmworld Программирование на ассемблере для начинающих и не только

Работа с файлами в DOS

Автор: xrnd | Рубрика: Исходники | 25-12-2010 | Распечатать запись

Эта статья лишь небольшой пример того, как можно работать с файлами, используя функции DOS. Я не буду описывать все возможные значения параметров и вдаваться в подробности. Это вы можете найти самостоятельно в справочнике.

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

Создание нового файла

Прежде, чем что-то записывать, необходимо создать файл. Для этого используется функция DOS 3Ch.

Имя файла должно быть в формате 8.3 — 8 символов имени и 3 символа расширения. Естественно, можно использовать только английский буквы, цифры и некоторые другие символы. Строка с именем файла должна заканчиваться нулевым байтом. Если файл уже существует, то его содержимое будет удалено.

Об ошибке можно узнать, проверяя значение флага CF (1 — ошибка, 0 — нет ошибки). Аналогично для других функций работы с файлами. Если флаг CF равен 0, то в регистре AX будет находиться дескриптор (или описатель) файла. Дескриптор — это просто специальное число, по которому операционная система отличает один открытый файл от другого.

Запись данных в файл

Запись в файл выполняется функцией DOS 40h. Этой функции нужно передать в регистре BX тот самый дескриптор, который был получен при создании файла.

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

Закрытие файла

После работы с файлом нужно его закрыть с помощью функции DOS 3Eh.

Если вы не закроете файл, то он будет закрыт системой при выходе из программы. Однако, хорошим стилем программирования является явное закрытие файла после завершения работы с ним.

Пример первый

Программа создаёт новый файл и записывает в него данные. Так как диск и директория не указаны, то файл создаётся в текущей папке. В данном примере в файл записываются 2 строки, получается текстовый файл. Можно работать с двоичными файлами, записывая любые байты, слова и т.д.

use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Перепрыгнуть данные ;——————————————————————————- ; Данные file_name db ‘hello.txt’,0 buffer db ‘asmworld.ru’,13,10,’Hello!’ size db 19 s_error db ‘Error!’,13,10,’$’ s_pak db ‘Press any key. $’ handle rw 1 ;Дескриптор файла ;——————————————————————————- ; Код start: mov ah,3Ch ;Функция DOS 3Ch (создание файла) mov dx,file_name ;Имя файла xor cx,cx ;Нет атрибутов — обычный файл int 21h ;Обращение к функции DOS jnc @F ;Если нет ошибки, то продолжаем call error_msg ;Иначе вывод сообщения об ошибке jmp exit ;Выход из программы @@: mov [handle],ax ;Сохранение дескриптора файла mov bx,ax ;Дескриптор файла mov ah,40h ;Функция DOS 40h (запись в файл) mov dx,buffer ;Адрес буфера с данными movzx cx,[size] ;Размер данных int 21h ;Обращение к функции DOS jnc close_file ;Если нет ошибки, то закрыть файл call error_msg ;Вывод сообщения об ошибке close_file: mov ah,3Eh ;Функция DOS 3Eh (закрытие файла) mov bx,[handle] ;Дескриптор int 21h ;Обращение к функции DOS jnc exit ;Если нет ошибки, то выход из программы call error_msg ;Вывод сообщения об ошибке exit: mov ah,9 mov dx,s_pak int 21h ;Вывод строки ‘Press any key. ‘ mov ah,8 ;\ int 21h ;/ Ввод символа без эха mov ax,4C00h ;\ int 21h ;/ Завершение программы ;——————————————————————————- ; Процедура вывода сообщения об ошибке error_msg: mov ah,9 mov dx,s_error int 21h ;Вывод сообщения об ошибке ret

В результате работы программы создаётся файл, который можно открыть блокнотом:

Открытие существующего файла

Для открытия файла используется функция DOS 3Dh. В отличие от создания файла, эта функция завершится ошибкой, если файл не существует.

Чтение данных из файла

Чтение из файла выполняется функцией DOS 3Fh.

Размер буфера для данных должен быть больше или равен количеству считываемых байтов. Обратите внимание, что в AX функция возвращает количество реально прочитанных байтов. Это количество может быть меньше требуемого, например, если файл слишком короткий.

Пример второй

Программа читает данные из текстового файла и выводит на консоль. Для того, чтобы вывести данные, нужно добавить символ ‘$’ в конец строки.

use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Перепрыгнуть данные ;——————————————————————————- ; Данные file_name db ‘hello.txt’,0 s_error db ‘Error!’,13,10,’$’ s_file db ‘—-[ file «Hello.txt» ]$’ endline db 13,10,’$’ s_pak db ‘Press any key. $’ buffer rb 81 ;80 + 1 байт для символа конца строки ‘$’ handle rw 1 ;Дескриптор файла ;——————————————————————————- ; Код start: mov ah,3Dh ;Функция DOS 3Dh (открытие файла) xor al,al ;Режим открытия — только чтение mov dx,file_name ;Имя файла xor cx,cx ;Нет атрибутов — обычный файл int 21h ;Обращение к функции DOS jnc @F ;Если нет ошибки, то продолжаем call error_msg ;Иначе вывод сообщения об ошибке jmp exit ;Выход из программы @@: mov [handle],ax ;Сохранение дескриптора файла mov bx,ax ;Дескриптор файла mov ah,3Fh ;Функция DOS 3Fh (чтение из файла) mov dx,buffer ;Адрес буфера для данных mov cx,80 ;Максимальное кол-во читаемых байтов int 21h ;Обращение к функции DOS jnc @F ;Если нет ошибки, то продолжаем call error_msg ;Вывод сообщения об ошибке jmp close_file ;Закрыть файл и выйти из программы @@: mov bx,buffer add bx,ax ;В AX количество прочитанных байтов mov byte[bx],’$’ ;Добавление символа ‘$’ mov ah,9 mov dx,s_file int 21h ;Вывод строки с именем файла mov cx,56 call line ;Вывод линии mov ah,9 mov dx,buffer int 21h ;Вывод содержимого файла mov dx,endline int 21h ;Вывод перехода на новую строку mov cx,80 call line ;Вывод линии close_file: mov ah,3Eh ;Функция DOS 3Eh (закрытие файла) mov bx,[handle] ;Дескриптор int 21h ;Обращение к функции DOS jnc exit ;Если нет ошибки, то выход из программы call error_msg ;Вывод сообщения об ошибке exit: mov ah,9 mov dx,s_pak int 21h ;Вывод строки ‘Press any key. ‘ mov ah,8 ;\ int 21h ;/ Ввод символа без эха mov ax,4C00h ;\ int 21h ;/ Завершение программы ;——————————————————————————- ; Процедура вывода сообщения об ошибке error_msg: mov ah,9 mov dx,s_error int 21h ;Вывод сообщения об ошибке ret ;——————————————————————————- ; Вывод линии ; CX — количество символов line: mov ah,2 ;Функция DOS 02h (вывод символа) mov dl,’-‘ ;Символ @@: int 21h ;Обращение к функции DOS loop @B ;Команда цикла ret

Результат работы программы:

Некоторые другие функции DOS для работы с файлами

Подробное описание смотрите в справочнике.

  • 5Bh — создание нового файла без удаления существующего;
  • 5Ah — создание файла с уникальным именем (например, временного файла);
  • 41h — удаление файла;
  • 42h — установка указателя чтения/записи;
  • 56h — переименование файла;
  • 43h — получение или изменение атрибутов файла;
  • 57h — получение или изменение метки времени файла;
  • 39h — создание папки;
  • 3Ah — удаление папки;
  • 3Bh — изменение текущей папки;
  • 47h — получение текущей папки.

Dos fn 45h: дублировать описатель файла dup

Эта глава описывает функции для выполнения операций ввод-вывода низкого уровня с помощью дескрипторов. Эти функции включают примитивы для функций ввода — вывода с более высоким уровнем, описанные в Главе 7 [Ввод — вывод на Потоках], также как функции для выполнения операций управления низкого уровня, для которых не имеется никаких эквивалентов на потоках. Ввод-вывод на уровне потоков более гибок и обычно более удобен; поэтому, программисты используют функции дескрипторного уровня только при необходимости. Вот несколько ситуаций, в которых могут понабиться дескрипторы:

  • Для чтения двоичных файлов в больших кусках.
  • Для чтения всего файла в ядро перед его синтаксическим анализом.
  • Для выполнения операций отличных от передачи данных, которая может быть выполнена только с дескриптором. (Вы можете использовать fileno, для получения дескриптора, соответствующего потоку.)
  • Для передачи дескриптора в дочерний процесс. (Дочерний может создавать собственный поток, для использования наследуемого описателя, но не может наследовать поток непосредственно.)

Этот раздел описывает примитивы для открытия и закрытия файлов, используя дескрипторы файла. Функции creat и open объявлены в файле ‘fcntl.h’, в то время как close объявлена в ‘unistd.h’. -Функция: int open (const char *filename, int flags[, mode_t mode])

Функция open создает и возвращает новый описатель файла для указанного файла. Первоначально, индикатор файловой позиции для файла находится в начале файла. Аргумент mode используется только, когда файл создан.

Аргумент flags управляет тем, как файл будет открыт. Это ­ битовая маска; Вы создаете значение поразрядным ИЛИ соответствующих параметров (используя оператор `|’ в C).

Аргумент flags должен включять точно одно из этих значений, для задания режима доступа к файлу:

Файл существует, но не читаем/перезаписываем как запрошено аргументом flags. EEXIST

И O_CREAT и O_EXCL — установлены, а именованный файл уже существует. EINTR

Операция open была прервана сигналом. См. Раздел 21.5 [Прерванные Примитивы] 3. EISDIR

Аргумент flags задает доступ для записи, а файл — каталог. EMFILE

Процесс имеет слишком много открытых файлов. ENFILE

Вся система, или возможно файловая система, которая содержит каталог, не может поддерживать любые дополнительные файлы открытыми в настоящее время. (Эта проблема не может случаться в системе GNU.) ENOENT

Именованный файл не существует, но O_CREAT не определен. ENOSPC

Каталог или файловая система, которая содержала бы новый файл,не может быть расширена, т. к. там не осталось дискового пространства. ENXIO

O_NONBLOCK и O_WRONLY установлены в аргументе flags, файл, именованный filename — FIFO (см. Главу 10 [Каналы и FIFO]), и никакой процесс имеет файл открытым для чтения. EROFS

Файл постоянно находится в файловой системе только для чтения и любой из O_WRONLY, O_RDWR, O_CREAT, и O_TRUNC ­ установлены в аргументе flags.

Функция open — основной примитив для fopen и freopen функций, которые создают потоки.

-Функция: int creat (const char *filename, mode_t mode)

Эта функция устаревает. Обращение: creat (filename, mode) эквивалентно: open (filename, O_WRONLY | O_CREAT | O_TRUNC, mode)

-Функция: int close (int filedes)

Функция закрывает дескриптор файла filedes. Закрытие файла имеет следующие последствия:

  • Описатель файла освобожден.
  • Любые блокировки записи, принадлежащие процессу на файле разблокирутся.
  • Когда все описатели файла, связанные с каналом или в порядке поступления были закрыты, любые читаемые обратно данные отброшены.

Нормальное возвращаемое значение — 0; значение -1 возвращается в случае ошибки.

Следующие errno условия ошибки определены для этой функции:

  • EBADF Filedes аргумент — не допустимый дескриптор файла.
  • EINTR Обращение было прервано сигналом. См. Раздел 21.5 [Прерванные Примитивы]. Вот пример правильной обработки EINTR:

Этот раздел описывает функции для выполнения ввода и вывода с помощьюю дескрипторов файла: read, write, и lseek. Эти функции объявлены в файле ‘ unistd.h ‘. -Тип данных: ssize_t

Этот тип данных используется для представления размеров блоков, которые могут быть прочитаны или записаны одиночной операцией. Он подобен size _t, но должен быть знаковым типом.

-Функция: ssize_t read (int filedes, void *buffer, size_t size)

Функция read читает до size байтов из файла с описателем filedes, сохраняя результаты в буфере. (Это — не обязательно символьная строка и не имеется никакого добавленного пустого символа завершения.)

Возвращаемое значение — число байтов фактически прочитанных. Оно может быть меньше чем size.

Нулевое значение указывает конец файла (за исключением того, если значение аргумента size является также нулем). Это не является ошибкой.

Если read возвращает по крайней мере один символ, не имеется никакого способа, которым Вы можете узнать, был ли конец файла достигнут. Но если Вы достигали конца, следующий read возвратит нуль.

В случае ошибки read возвращает -1. Следующие errno условия ошибки определены для этой функции: EAGAIN

Обычно, когда никакой ввод недоступен, read ждет какого-нибудь ввода. Но если установлен флаг O_NONBLOCK (см. Раздел 8.10 [Флаги Состояния Файла]), read возвращается немедленно не читая никаких данных, и сообщает эту ошибку.

Примечание о Совместимости: Большинство версий BSD UNIX использует различный код ошибки для EWOULDBLOCK. В библиотеке GNU, EWOULDBLOCK — синоним EAGAIN, так что не имеет значения, акое название Вы используете.

На некоторых системах, чтение большого количества данных из символьного специального файла может также выдавать ошибку EAGAIN, если ядро не может найти достаточно памяти для страниц пользователя. Это ограничение для устройств, которые передают с прямым доступом в память, т. е. не включают терминалы, так как они всегда используют отдельные буфера внутри ядра. EBADF

Filedes аргумент — не допустимый описатель файла. EINTR

Чтение было прервано сигналом, в то время как он ждал ввода.

См. Раздел 21.5 [Прерванные Примитивы]. EIO Для многих устройств, и для файлов на диске, этот код ошибки указывает аппаратную ошибку. EIO также происходит, когда фоновый процесс пробует читать с терминала управления, и нормальное действие остановки процесса, т. е. Посылка сигнала SIGTTIN не работает. Это может случиться, если сигнал блокируется или игнорируется, или т. к. группа процесса — orphaned. См. Главу 24 [Управление заданиями].

Функция read — основной примитив для всех функций, которые читают из потоков, типа fgetc.

-Функция: ssize_t write (int filedes, const void *buffer, size_t size)

Функция write пишет до size байтов из буфера в файл с описателем filedes. Данные в буфере — не обязательно символьная строка и вывод пустого символа подобен любому другому.

Возвращаемое значение — число байтов, фактически записанных. Это — обычно size, но могло бы быть и меньшее количество. В случае ошибки, write возвращает -1. Следующие errno условия ошибки определены для этой функции: EAGAIN

Обычно, write блокируется до завершения операции записи. Но если для файла устанавлен O_NONBLOCK флаг (см. Раздел 8.7 [Операции Управления]), она возвращается немедленно не позводя записи любых данных, и сообщает эту ошибку. Пример ситуации, котаря могла бы вызывать блокировани процесса на выводе, запись в терминальное устройство, которое поддерживает управление потоком данных, где вывод был приостановлен получением символа STOP.

Примечание Совместимости: Большинство версий BSD UNIX использует различный код ошибки для EWOULDBLOCK. В библиотеке GNU, EWOULDBLOCK ­ синоним для EAGAIN, так что не имеет значения, какое название Вы используете.

Аргумент Filedes — не допустимый дескриптор файла. EFBIG

Размер файла больший чем реализация, может поддерживать. EINTR

Операция write была прервана сигналом, в то время как она была блокирована, и ждала завершения. См. Раздел 21.5 [Прерванные Примитивы]. EIO

Для многих устройств, и для файлов на диске, этот код ошибки указывает аппаратную ошибку. EIO также происходит, когда фоновый процесс пробует читать с терминала управления, и нормальное действие остановки процесса, посылая сигнал SIGTTIN не работает. Это может случиться, если сигнал блокируется или игнорируется, или т. к. группа процесса — orphaned. См. Главу 24 [Управление заданиями]. ENOSPC

переполнение устройства. EPIPE

Эта ошибка возвращается, когда Вы пробуете писать в канал или в FIFO, который не открыт для чтения процессом. Когда это случается, сигнал SIGPIPE также посылается в процесс; см. Главу 21 [Обработка Сигнала]. Если Вы не предотвращаете EINTR ошибки, Вам следует проверять errno после каждого выдающего ошибку обращения к write, и если ошибка была EINTR, Вы должны просто повторить обращение. См. Раздел 21.5 [Прерванные Примитивы]. Простой способ реализовать это — макрокомандой TEMP_FAILURE_RETRY, следующим образом:

Точно как Вы можете устанавливать файловую позицию потока функцией fseek, Вы можете устанавливать файловую позицию дескриптора функцией lseek. Она определяет позицию в файле для следующей операции read или write. См. Раздел 7.15 [Позиционирование Файла], для подробной информации относительно файловой позиции и что это означает.

Для получения текущего значения файловой позиции из описателя, используйте lseek (desc, 0, SEEK_CUR). -Функция: off_t lseek (int filedes, off_t offset, int whence)

Функция lseek используется, чтобы изменить файловую позицию файла с описателем filedes. Аргумент whence определяет, как смещение должно интерпретироваться, таким же образом как в функции fseek, и может быть одной из символических констант SEEK_SET, SEEK_CUR, или SEEK_END. SEEK_SET

Определяет, что whence — яисло символов от начала файла. SEEK_CUR

Определяет, что whence — число символов от текущей файловой позиции. Этот число может быть положительно или отрицательно. SEEK_END

Определяет, что whence — число символов с конца файла. Отрицательное число определяет позицию внутри текущего тела файла; положительное число определяет позицию после текущего конца. Если Вы устанавливаете позицию после текущего конца, и фактически записываете данные, Вы расширяете файл нулями до этой позиции.

Возвращаемое значение lseek — обычно возникающая в результате файловая позиция, измеряемая в байтах от начала файла. Вы можете использовать это средство вместе с SEEK_CUR для чтения текущей файловой позиции.

Вы можете устанавливать файловую позицию после текущего конца файла. Это делает файл больше; lseek никогда не изменяет файл. Но последующий вывод в ту позицию расширит файла.

Если файловая позиция не может быть изменена, или операция выполняется некоторым недопустимым способом, lseek возвращает значение -1. Следующие errno условия ошибки определены для этой функции: EBADF

Filedes — не допустимый описатель файла. EINVAL

Значение аргумента whence не допустимо, или возникающее в результате смещение файла не допустимо.

filedes соответствует каналу или FIFO, который не может быть позиционирован. ( Могут иметься другие виды файлов, которые также не могут быть позиционированы, но в этих случаях поведение не определено.) Функция lseek — основной примитив для fseek, ftell и rewind функций, которые функционируют на потоках вместо описателей файла.

Вы можете иметь многократные описатели для того же самого файла, если Вы открываете файл больше чем один раз, или если Вы дублируете описатель с dup. Дескрипторы, которые исходят из отдельных обращений open, имеют независимые файловые позиции; использование lseek на одном дескрипторе не произодит никакого эффекта на другой. Например,

Напротив, описатели, сделанные дублированием совместно используют общую файловую позицию с первоначальным описателем, который был дублирован. Изменение файловой позиции одного из дубликатов, включая чтение или запись данных, воздействует на все из них. Таким образом, например,

Будет читать четыре символа, начиная с 1024-го символа ‘foo’, и еще четыре символа, начиная с 1028-го символа.

-Тип данных: оff_t

Это — арифметический тип данных, используемый, чтобы представить размеры файла. В системе GNU, он эквивалентен fpos_t или long int. Эти три синонима константы ‘SEEK_. ‘ существуют ради совместимости с более старыми BSD системами. Они определены в двух различных файлах: ‘fcntl.h’ и ‘sys/file.h’.

L_SET синоним для SEEK_SET.

L_INCR синоним SEEK_CUR.

L_XTND синоним SEEK_END.

Определяя дескриптор файла с помощью open, Вы можете создавать поток для него функцией fdopen. Вы можете получить основной описатель файла для существующего потока функцией fileno. Эти функции объявлены в заглавном файле ‘stdio.h’. -Функция: FILE * fdopen (int filedes, const char *opentype)

Функция fdopen возвращает новый поток для описателя файла filedes. Opentype аргумент интерпретируется таким же образом как в функции fopen (см. Раздел 7.3 [Открытие Потоков]), за исключением того, что опция ‘b’ не разрешается; это оттого, что GNU не делает никакого различия между текстом и двоичными файлами. Также, ‘w’ и ‘w+’ не вызывают усечение файла; они воздействуют только при открытии файла, а в этом случае, файл уже открыт. Вы должны удостовериться, что opentype аргумент соответствует фактическому режиму дескриптора файла.

Возвращаемое значение — новый поток. Если поток не может быть создан (например, если режимы для файла, обозначенного дескриптором файла не разрешают доступ, заданный opentype аргументом), взамен возвращается пустой указатель.

Для примера, показывающего использование функции fdopen, см. Раздел 10.1 [Создание Канала].

-Функция: int fileno (FILE *stream)

Эта функция возвращает описатель файла, связанный с указанным потоком. Если обнаружена ошибка (например, если поток не допустим) или если поток, не делает ввод — вывод в файл, fileno возвращает — 1.

Имеются также символические константы, определенные в ‘unistd.h’ для описателей файла, принадлежащих к стандартным потокам stdin, stdout, и stderr; см. Раздел 7.2 [Стандартные Потоки]. STDIN_FILENO

Эта макрокоманда имеет значение 0, которое является дескриптором файла для стандартного ввода. STDOUT_FILENO

Эта макрокоманда имеет значение 1, которое является дескриптором файла для стандартного вывода. STDERR_FILENO

Эта макрокоманда имеет значение 2, которое является дескриптором файла для стандартного вывода ошибки.

Вы можете иметь многочисленные дескрипторы файла и потоки (назывем и потоки и дескрипторы ‘каналами’, для краткости), связанными с одним и тем же файлом, но Вы должны соблюдать осторожность, чтобы избежать путаницы между каналами. Имеются два случая, для рассмотрения: связанные каналы, которые совместно используют одино значение файловой позиции, и независимые каналы которые имеют свои собственные файловые позиции.

Самое лучшее использовать только один канал в вашей программе для фактической передачи данных в любой данный файл, за исключением того, когда весь доступ создан для ввода. Например, если Вы открываете канал (кое-что Вы можете делать только на уровне дескрипторов файла), или делать весь ввод — вывод через дескриптор, или создавать поток с fdopen, и тогда делать весь ввод — вывод через поток.

Связанные Каналы

Каналы, которые исходят из одного открытия, совместно используют ту же самую файловую позицию; мы называем их связанными каналами. Связанные каналы кончаются, когда Вы делаете поток из дескриптора, используя fdopen, и когда Вы получаете описатель из потока с fileno, и когда Вы копируете описатель с dup или dup2. Для файлов, которые не поддерживают, произвольный доступ, типа терминалов и канадов, все каналы действительно связаны. На файлах прямого доступа, все выходные потоки конкатенирующего типа действительно связаны друг с другом.

Если Вы использовали поток для ввода — вывода, и Вы хотите делать ввод — вывод, используя другой канал (или поток или дескриптор) который связан с этим, Вы должны сначала очистить поток, который Вы использовали. См. Раздел 8.5.3 [Очистка Потоков].

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

Независимые Каналы

Когда Вы открываете каналы (потоки или описатели) отдельно, каждый канал имеет собственную файловую позицию. Они называются независимыми каналами.

Система обрабатывает каждый канал независимо. В большинстве случаев, это совершенно предсказуемостно и естественно (особенно для ввода): каждый канал может читать или писать последовательно в собственном месте в файле. Однако, если некоторые из каналов — потоки, Вы должны соблюдать предосторожности:

  • Вы должны oчистить выходной поток после использования, перед выполнением чего — нибудь еще, что могло бы читать или писать в ту же самую часть файла.
  • Вы должны oчистить входной поток перед чтением данных, которые могут изменяться использованием независимого канала. Иначе, Вы можете читать устаревшие данные, которые были в буфере потоков.

Если Вы выводите по одному каналу в конец файла, это конечно оставит другие независимые каналы, позиционированные где-нибудь перед новым концом. Если Вы хотите, чтобы они вывели в конец, Вы должны установить их файловые позиции в конец файла. (В этом нет нужды, если Вы используете описатель конкатенирующего типа или поток; они всегда выводят в текущий конец файла.)

Двум каналам невозможно иметь отдельные указатели файла для файла, который не поддерживает произвольный доступ. Таким образом, каналы для чтения или записи в такие файлы всегда связаны. Каналы конкатенирующего типа также всегда связаны. Для этих каналов, соблюдайте правила связанных каналов; см. Раздел 8.5.1 [Связанные Каналы].

Очистка Потоков

В системе GNU, Вы можете очистить любой поток функцией fclean: -Функция: int fclean (FILE *stream)

Очищает указанный поток так, чтобы буфер был пуст. На других системах, Вы можете использовать fflush, чтобы oчистить поток в большинстве случаев. Вы можете пропускать fclean или fflush, если Вы знаете, что поток уже пуст. Поток пуст всякий раз, когда буфер пуст. Например, небуферизованный поток всегда пуст. Входной поток, который находится в конце файла, пуст. Буферизированный строчно поток пуст, когда последний выходной символ был символ перевода строки.

Имеется один случай, в котором сброс потока является невозможным на большинстве систем. Тогда, когда поток делает ввод из файла, не являющегося файлом прямого доступа. Такие потоки обычно читают вперед, и когда файл ­ не произвольного доступа, то нет никакого способа сбросить обратно данные излишка уже прочтитанные. Когда входной поток читается из файла прямого доступа, fflush oчищает поток, но оставляет указатель файла в непредсказуемом месте; Вы должны установить указатель файла перед выполнением любого дальнейшего ввода — вывода. В системе GNU, используя fclean Вы избежите обе эти проблемы.

fflush также делает закрытие выходного потока, так что это ­ допустимый способ очистки выходного потока. В системе GNU, закрытие входного потока вызывает fclean.

Вы не нуждаетесь в чистке потока перед использованием дескриптора для операций управления, типа установки режимов терминала; эти операции не воздействуют на файловую позицию и не зависят от нее. Вы можете использовать любой дескриптор для этих операций, и на все каналы воздействовать одновременно. Однако, текст уже ‘выведенный’ в поток но все еще буферизируемый потоком будет подчинен новым режимам терминала. Чтобы удостовериться что ‘прошлый’ вывод подчинен установкам терминала, которые были в действительности во время, сбрасывайте выходные потоки для того терминала перед установкой режимов. См. Раздел 12.4 [Режимы Терминала].

Иногда программа должна принять ввод на нескольких входных каналах всякий раз, когда ввод прибывает. Например, некоторые рабочие станции могут иметь устройства типа планшета отцифровывания, поля функциональной клавиши, или поля набора кода, которые соединены через нормальные асинхронные последовательные интерфейсы; хороший стиль интерфейса пользователя требует, чтобы ответ немедленно воздействовал на любое устройство. Другой пример — программа, которая действует как сервер для нескольких других процессов через каналы или гнезда.

Вы не можете обычно использовать для этой цели read, потому что она блокирует программу до ввода на одном указанном описателе файла; ввод на других каналах не будет иметь действия. Вы могли бы установить режим не блокирования и опрашивать каждый описатель файла по очереди, но это очень неэффективно.

Лучшее решение состоит в том, чтобы использовать функцию выбора. Она блокирует программу до ввода или вывода по заданному набору описателей файла, или по таймеру. Это средство объявлено в заглавном файле ‘sys/types.h’.

Наборы описателей файла для функции выбора определены как объекты fd_set. Вот описание типа данных и некоторых макрокоманд для управления этих объектов.

fd_set (тип данных)

Этот тип данных представляет наборы описателей файла для функции выбора. Это — фактически битовый массив. int FD_SETSIZE (макрос)

Значение этой макрокоманды — максимальное число описателей файла, о которых объект fd_set может содержать информацию. На системах с фиксированным максимальным номером, FD_SETSIZE — по крайней мере это число. На некоторых системах, включая GNU, не имеется никакого абсолютного ограничения числа описателей, но эта макрокоманда все еще имеет постоянное значение, которые управляет числом битов в fd_set. void FD_ZERO (fd_set *set) (макрос)

Эта макрокоманда инициализирует набор наборов описателей файла, как пустое множество. void FD_SET (int filedes, fd_set *set) (макрос)

Эта макрокоманда добавляет filedes к набору описателей файлов. void FD_CLR (int filedes, fd_set *set) (макрос)

Эта макрокоманда удаляет filedes из набора дескрипторов файлов. int FD_ISSET (int filedes, fd_set *set) (макрос)

Эта макрокоманда возвращает значение отличное от нуля (истина), если filedes — элемент набора описателей файлов, и нуль (ложь) иначе.

Вот описание функции выбора непосредственно.

Описатели файла, заданные read_fds аргументом проверяются, являются ли они готовыми для чтения; write_fds описатели файла проверяются, являются ли они готовыми записи; и except_fds описатели файла задают исключительные условия. Вы можете передавать пустой указатель для любого из этих аргументов, если Вы не заинтересованы проверкой этого вида условия.

‘Исключительные условия’ не означают, что ошибки сообщаются немедленно, когда выполнен ошибочный системный вызов. Они включают условия, типа присутствия срочного сообщения на гнезде. (См. Главу 11 [Гнезда], для уточнения информации о срочных сообщениях.)

Функция выбора проверяет только первые nfds описателей файла. Обычно она передает FD_SETSIZE как значение этого аргумента.

Блокировка по времени определяет максимальное время ожидания. Если Вы передаете пустой указатель в качестве этого аргумента, это означает, что блокировать неопределенно, пока один из описателей файла не готов. Иначе, Вы должны обеспечить время в формате struct timeval; см. Раздел 17.2.2 [Календарь с высоким разрешением]. Определите нуль как время (struct timeval содержащий все нули) если Вы хотите выяснять, какие описатели готовы в данный момент, без ожидания.

Нормальное возвращаемое значение — общее число готовых описателей файла во всех наборах. Каждый из наборов аргументов записан поверх информацией относительно описателей, которые являются готовыми для соответствующей операции. Таким образом, чтобы видеть, готов ли данный описатель desc для ввода, используйте FD_ISSET (desc, read_fds) после возврата select.

Если select возвращается, потому что период блокировки по времени истекает, то возвращаемое значение — нуль.

Любой сигнал заставит select возвращаться немедленно. Так, если ваша программа использует сигналы, Вы не можете полагаться на select, чтобы ждать полное заданное время. Если Вы хотите убедиться в правильности ожидания, Вы должны проверить EINTR и повторять select с расчетной блокировкой по времени, основанной на текущем времени. См. пример ниже. См. также Раздел 21.5 [Прерванные Примитивы].

Если происходит ошибка, select возвращает -1 и не изменяет аргумент наборов описателей файла. Следующие errno условия ошибки определены для этой функции: EBADF

Один из набора описателей файла определил недопустимый дескриптор файла. EINTR

Операция была прервана сигналом. См. Раздел 21.5 [Прерванные Примитивы]. EINVAL

Аргумент блокировки по времени недопустим; один из компонентов отрицателен или слишком большой. Примечание о Переносимости: функция select — BSD возможность UNIX. Вот пример, показывающий, как Вы можете использовать select, чтобы установить период блокировки по времени для чтения из дескриптора файла. Input_timeout функция блокирует процесс вызова, пока ввод не доступен (на описателе файла), или пока период блокировки по времени не истек.

Этот раздел описывает, как Вы можете выполнять различные другие операции с дескрипторами файла, типа запроса или установки флагов, описывающих состояние описателя файла, манипулирования блокировками записи, и т.п.. Все эти операции выполняются функцией fcntl.

Второй аргумент fcntl функции — команда, которая определяет которую операцию выполнить. Функция и макрокоманды, которые обозначают различные флаги, объявлены в заглавном файле ‘fcntl.h’. (Многие из этих флагов также используются функцией open; см. Раздел 8.1 [Открытие и Закрытие Файлов].) -Функция: int fcntl (int filedes, int command, . )

Функция fcntl выполняет операцию, заданную командой, на описателе файла filedes. Некоторые команды требуют, чтобы были обеспечены дополнительные аргументы. Эти дополнительные аргументы и возвращаемое значение и условия ошибки даны в детализированных описаниях индивидуальных команд.

Вот краткий список различных команд. F_DUPFD

Дублирует дескриптор файла (возвращает другой дескриптор файла, указывающий на тот же самый открытый файл). См. Раздел 8.8 [Дублирование Дескрипторов]. F_GETFD

Получает флаги, связанные с описателем файла. См. Раздел 8.9 [Дескрипторные Флаги]. F_SETFD Устанавливает флаги, связанные с дескриптором файла. См. Раздел 8.9 [Дескрипторные Флаги]. F_GETFL

Получает флаги, связанные с открытым файлом. См. Раздел 8.10 [Флаги Состояния Файла]. F_SETFL

Устанавливает флаги, связанные с открытым файлом. См. Раздел 8.10 [Флаги Состояния Файла]. F_GETLK

Получает блокировку файла. См. Раздел 8.11 [Блокировки Файла].

Устанавливает или снимает блокировку файла. См. Раздел 8.11 [Блокировки Файла]. F_SETLKW

Подобен F_SETLK, но ждет завершения. См. Раздел 8.11 [Блокировки Файла]. F_GETOWN

Получает процесс или ID группы процессов, чтобы получить сигналы SIGIO. См. Раздел 8.12 [Ввод Прерывания]. F_SETOWN

Устанавливает процесс или ID группы процессов, чтобы получить сигналы SIGIO. См. Раздел 8.12 [Ввод Прерывания].

Вы можете дублировать дескриптор файла, или зарезервировать другой дескриптор файла, который относится к тому же самому открытому файлу, что и первый. Двойные дескрипторы совместно используют одну и ту же файловую позицию и один набор флагов состояния файла (см. Раздел 8.10 [Флаги Состояния Файла]), но каждый имеет собственный набор флагов дескриптора файла (см. Раздел 8.9 [Дескрипторные Флаги]).

Основное использование дублирования дескриптора файла это переадресация ввода или вывода: то есть замена файла или канала, которому указанный дескриптор файла соответствует.

Вы можете выполнять эту операцию, используя fcntl функцию с командой F_DUPFD, но имеются также удобные функции dup и dup2 для дублирования дескрипторов.

Fcntl функция и флаги объявлена в ‘fcntl.h’, в то время как прототипы для dup и dup2 находятся в файле ‘unistd.h’. -Функция: int dup (int old)

Эта функция копирует дескриптор old в первый доступный дескрипторный номер (первый номер не открытый сейчас). Это эквивалентно fcntl (old, F_DUPFD, 0).

-Функция: int dup2 (int old, int new)

Эта функция копирует дескриптор old в дескриптор new.

Если оld — недопустимый дескриптор, то dup2 не делает ничего. Иначе, новый дубликат old заменяет любое предыдущее значение дескриптора new, как будто он был закрыт сначала.

Если оld и new — различные числа, и old — допустимый дескрипторный номер, то dup2 эквивалентен:

Эта макрокоманда используется как аргумент команды fcntl, для копирования дескриптора файла, данного как первый аргумент.

Форма обращения в этом случае:

Возвращаемое значение из fcntl с этой командой — обычно значение нового дескриптора файла. Возвращаемое значение -1 указывает ошибку. Следующие errno условия ошибки определены для этой команды: EBADF

Аргумент old недопустим. EINVAL

Next_filedes аргумент недопустим. EMFILE

Дескрипторов файла, доступных вашей программе, больще нет. ENFILE

— не возможный код ошибки для dup2, потому что dup2 не создает новое открытие файла; двойные дескрипторные подпадают под ограничение, которое указывает ENFILE.

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

Вот пример, показывающий, как использовать dup2, чтобы делать переадресацию. Обычно, переадресация стандартных потоков (подобно stdin) выполняется командным интерпретатором или подобной программой перед вызовом одной из запускаемых функций (см. Раздел 23.5 [Выполнение Файла]) чтобы выполнить новую программу в дочернем процессе. Когда новая программа выполнена, она создает и инициализирует стандартные потоки, чтобы указать на соответствующие дескрипторы файла, прежде, чем функция main вызывается.

Так, чтобы переназначить стандартный ввод в файл, оболочка могла бы делать что — нибудь вроде:

Флаги дескриптора Файла — разнообразные атрибуты дескриптора файла. Эти флаги связаны со специфическими дескрипторами файла, так, что если Вы создаете двойные дескрипторы файла из одиночного открытия файла, то каждый дескриптор имеет собственный набор флагов.

В настоящее время имеется только один флаг дескриптора файла: FD_CLOEXEC, который заставляет дескриптор быть закрытым если Вы используете любую из запускаемых функций (см. Раздел 23.5 [Выполнение Файла]).

Символы в этом разделе определены в заглавном файле ‘fcntl.h’. int F_GETFD (макрос)

Эта макрокоманда используется как аргумент команды fcntl, чтобы определять, что она должна возвратить флаги дескриптора файла, связанные с filedes аргументом.

Нормальное возвращаемое значение из fcntl с этой командой ­ неотрицательное число, которое может интерпретироваться как поразрядное OR индивидуальных флагов (за исключением того, что в настоящее время имеется только один флаг).

В случае ошибки, fcntl возвращает -1. Следующие errno условия ошибки определены для этой команды: EBADF filedes аргумент недопустим.

int F_SETFD (макрос)

Эта макрокоманда используется как аргумент команды fcntl, для определения, что она должна установить флаги дескриптора файла, связанные с filedes аргументом. Она требует третий int аргумент, чтобы определить новые флаги, так что форма обращения:

Следующая макрокоманда определена для использования как флаг дескриптора файла с fcntl функцией. Значение — константа integer пригодное для использования как значение битовой маски.

int FD_CLOEXEC (макрос)

Этот флаг определяет, что дескриптор файла должен быть закрыт, когда вызывается запускаемая функция; см. Раздел 23.5 [Выполнение Файл]. Когда дескриптор файла размещен (как с open или dup), этот бит первоначально очищен на новом описателе файла, означая, что дескриптор останется в живых в новой программе после запуска.

Если Вы хотите изменять флаги дескриптора файла, Вы должны получить текущие флаги с F_GETFD и изменять значение. Не думайте, что флаги, перечисленные здесь — единственные, которые реализованы, ваша программа может быть будет выполняться через годы, и тогда может существовать большее количество флагов. Например, вот функция, чтобы устанавливать или очистить флаг FD_CLOEXEC без того, чтобы изменять любые другие флаги:

Флаги состояния Файла используются, чтобы определить атрибуты открытия файла. В отличие от флагов дескриптора файла, обсужденных в Разделе 8.9 [Дескрипторные Флаги], флаги состояния файла разделяются дублированными дескрипторами файла, следующими из одиночного открытия файла.

Флаги состояния файла инициализируются функцией open из аргумента флагов функции open. Некоторые из флагов значимы только в open и не вспоминаются впоследствии; многие из оставшихся не могут впоследствии быть изменены, хотя Вы можете читать их значения, исследуя флаги состояния файла.

Несколько флагов состояния файла могут быть изменены, в любое время используя fcntl. Они включают O_APPEND и O_NONBLOCK.

Символы в этом разделе определены в заглавном файле ‘fcntl.h’. int F_GETFL (макрос)

Эта макрокоманда используется как аргумент команды fcntl, для чтения флагов состояния файла для файла открытого с описателем filedes.

Нормальное возвращаемое значение из fcntl с этой командой ­ неотрицательное число, которое может интерпретироваться как поразрядное ИЛИ индивидуальных флагов. Флаги закодированы так же, как аргумент флагов для open (см. Раздел 8.1 [Открытие и Закрытие Файлов]), но здесь значимы только режимы доступа файла и O_APPEND и O_NONBLOCK флаги. Так как режимы доступа файла — не одноразрядные значения, Вы можете маскировать другие биты в возвращенных флагах с O_ACCMODE, чтобы сравнить их.

В случае ошибки, fcntl возвращает -1. Следующие errno условия ошибки определены для этой команды: EBADF filedes аргумент недопустим.

-Макрос: int F_SETFL

Эта макрокоманда используется как аргумент команды fcntl, для установки флагов состояния файла для открытого файла, соответствующего filedes аргументу. Эта команда требует третьего int аргумента, чтобы определить новые флаги, так что обращение походит на это:

Нормальное возвращаемое значение из fcntl с этой командой ­ неопределенное значение отличное от -1, которое указывает ошибку. Условия ошибки — такие же как для команды F_GETFL.

Следующие макрокоманды определены для анализа и построения значений флага состояния файла:

  • O_APPEND — бит, который делает возможным конкатенирующий режим для файла. Если установлен, то все операции write пишут данные в конце файла, расширяя его, независимо от текущей файловой позиции.
  • O_NONBLOCK Бит, который делает возможным режим неблокирования для файла. Если этот бит установлен, запрос чтения в файле может возвращаться немедленно с состоянием отказа, если не имеется никакого немедленно доступного ввода кроме блокирования. Аналогично, запросы write могут также возвращаться немедленно с состоянием отказа, если вывод нельзя написать немедленно.
  • O_NDELAY Это — синоним для O_NONBLOCK, предусматривающий совместимость с BSD.

-Макрос: int O_ACCMODE

Эта макрокоманда замещает маску, которая может быть поразрядна AND со значением флага состояния файла, чтобы произвести значение, представляющее режим доступа файла. Режим будет O_RDONLY, O_WRONLY, или O_RDWR.

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

Исключительная блокировка или блокировка записи дает монопольный доступ процессу для записи в заданной части файла. В то время как установлена блокировка никакой другой процесс не может блокировать эту часть файла.

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

Функции read и write фактически не выясняет, имеются ли блокировки в данном месте.

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

Блокировки связаны с процессами. Процесс может иметь только один вид набора блокировок для каждого байта данного файла. Когда любой дескриптор файла для того файла закрыт процессом, все блокировки, которые обрабатывают связи с тем файлом, опущены, даже если блокировки были сделаны, используя другие описатели, которые остаются открытыми. Аналогично, блокировки опущены, когда процесс выходит, и не наследуются дочерними созданными процессами (см. Раздел 23.4 [Создание Процесса]).

При создании блокировки, используйте struct flock, чтобы определить какую блокировку и где Вы хотите выполнить. Этот тип данных и связанные макрокоманды для fcntl функции объявлен в заглавном файле ‘fcntl.h’.

Эта структура используется с fcntl функцией, чтобы описать блокировку файла. Она имеет следующие элементы:

Эта макрокоманда используется как аргумент команды fcntl, для определения, что она должна получить информацию относительно блокировки. Эта команда требует третьего аргумента типа struct flock *, чтобы быть переданной к fcntl, так, чтобы форма обращения была:

Вы должны определить тип блокировки F_WRLCK, если Вы хотите выяснять относительно блокировок чтения и записи, или F_RDLCK, если Вы хотите выяснять относительно блокировок только записи.

Может иметься больше чем одна блокировка, воздействующая на область, заданную lockp аргументом, но fcntl только возвращает информацию относительно одной из них. l_whence элемент структуры lockp установлен в SEEK_SET и l_start и l_len набор полей, чтобы идентифицировать блокированную область.

Если никакая блокировка не применяется, единственное изменение для структуры lockp, должно модифицировать l_type в значение F_UNLCK.

Нормальное возвращаемое значение из fcntl с этой командой ­ неопределенное значение отличное от -1, которое зарезервировано, чтобы указать ошибку. Следующие errno условия ошибки определены для этой команды: EBADF filedes аргумент недопустим.

Или lockp аргумент не определяет допустимую информацию блокировки, или файл, связанный с filedes не поддерживает блокировки. -Макрос int F_SETLK

Эта макрокоманда используется как аргумент команды fcntl, для определения, что она должна установить или снять блокировку. Эта команда требует третьего аргумента типа struct flock *, так, чтобы форма обращения была:

Если блокировка не может быть установлена, fcntl возвращается немедленно со значением -1. Эта функция не блокирует ожидание пока другие процессы снимут блокировки. Если fcntl преуспевает, она возвращает значение отличное от -1.

Следующие errno условия ошибки определены для этой функции: EACCES

Блокировка не может быть установлена, потому что это блокировано существующей блокировкой на файле.

Некоторые системы используют EAGAIN в этом случае, и другие системы используют EACCES; ваша программа должна обработать их одинаково, после F_SETLK. EBADF

Также: filedes аргумент недопустим; Вы запросили блокировку чтения, но filedes — не открыт для чтения; или, Вы запросили блокировку записи, но filedes — не открыт для записи. EINVAL

Или lockp аргумент определяет недопустимую информацию блокировки, или файл, связанный с filedes не поддерживает блокировки. ENOLCK

Система работает без ресурсов блокировки файла; имеются уже слишком много блокировок файла.

Хорошо разработанные файловые системы никогда не сообщают эту ошибку, потому что они не имеют никакого ограничения на число блокировок. Однако, Вы должны все еще принимать во внимание возможности этой ошибки, поскольку это может следовать из доступа к сети к файловой системе на другой машине. int F_SETLKW (макрос)

Эта макрокоманда используется как аргумент команды fcntl, для определения, что она должна установить или снять блокировку. Это ­ тоже что команда F_SETLK, но заставляет процесс блокировать (или ждать) пока запрос не будет определен.

Эта команда требует третьего аргумента типа struct flock *, как для команды F_SETLK.


Fcntl возвращаемые значения и ошибки — те же что для команды F_SETLK, но эти дополнительные errno условия ошибки определены для этой команды:

Функция была прервана сигналом, во время ожидания. См. Раздел 21.5 [Прерванные Примитивы]. EDEADLK

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

Следующие макрокоманды определены для использования как значения для l_type элемента структуры flock. Значения — константы integer. F_RDLCK

Эта макрокоманда используется, чтобы установить блокировку чтения. F_WRLCK

Эта макрокоманда используется, чтобы установить блокировку записи. F_UNLCK

Эта макрокоманда используется, чтобы установить, что область разблокируется.

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

Если программа также нуждается в чтении из файла и хочет удостовериться, что содержимое файла находится в непротиворечивом состоянии, то она может также использовать блокировку чтения. В то время как блокировка чтения установлена, никакой другой процесс не может блокировать эту часть файла для записи.

Не забудьте, что блокировки файла — только произвольный протокол для управления доступом к файлу. Все еще имеется возможность для доступа к файлу программами, которые не используют протокол блокировки.

Если Вы устанавливаете FASYNC флаг состояния на дескрипторе файла (см. Раздел 8.10 [Флаги Состояния Файла]), сигнал SIGIO посланы всякий раз, когда производится ввод или вывод, становится возможным на этом описателе файла. Процесс или группа процессов, может быть выбрана чтобы получить сигнал, используя команду F_SETOWN для fcntl функции. Если дескриптор файла является гнездом, он также, выбирает получателя сигналов SIGURG, которые возникают, когда внепоточные данные прибывает в это гнездо; см. Раздел 11.8.8 [Внепоточные Данные].

Если дескриптор файла соответствует терминалу, то SIGIO сигналы посылаются группе приоритетного процесса терминала. См. Главу 24 [Управление заданиями].

Символы в этом разделе определены в заглавном файле ‘fcntl.h’. -Макрос int F_GETOWN

Эта макрокоманда используется как аргумент команды fcntl, для определения того, что она должна получить информацию относительно процесса или группы процессов, которой посланы сигналы SIGIO. (Для терминала, это — фактически приоритетный ID группы процессов, которую Вы можете получать использованием tcgetpgrp; см. Раздел 24.7.3 [Функции Доступа Терминала].)

Возвращаемое значение интерпретируется как ID процесса; если оно отрицательно, то абсолютное значение — ID группы процессов.

Следующее errno условие ошибки определено для этой команды: EBADF

Filedes аргумент недопустим. int F_SETOWN (макрос)

Возвращаемое значение из fcntl с этой командой — -1 в случае ошибки и некоторое другого значения если обращение успешно. Следующие errno условия ошибки определены для этой команды: EBADF

Filedes аргумент недопустим. ESRCH

Не имеется никакого процесса или группы процессов, соответствующей pid.

Dos fn 45h: дублировать описатель файла dup

Функция DuplicateHandle делает копию дескриптора объекта. Продублированный дескриптор относится к тому же самому объекту, что и исходный дескриптор. Поэтому, любое изменение объекта отражается через оба дескриптора. Например, дескриптор файла, зарегистрированный для текущего файла, является всегда одним и тем же для обоих дескрипторов.

[in] Дескриптор процесса, дескриптор которого дублируется.

Windows NT /2000/XP: дескриптор должен иметь право доступа PROCESS_DUP_HANDLE . Для получения дополнительной информации, см. статью Защита процесса и права доступа.

[in] Дескриптор, который дублируется. Это открытый дескриптор объекта, который является правильным применительно к исходному процессу. Перечень объектов, дескрипторы которых могут быть продублированы, см. нижеследующем разделе Замечаний.

[in] Дескриптор процесса, который должен получить продублированный дескриптор. Дескриптор должен иметь право доступа PROCESS_DUP_HANDLE .

[out] Указатель на переменную, которая получает значение продублированного дескриптора. Это значение дескриптора правильно применительно к целевому процессу.

Если параметр lpTargetHandle имеет значение ПУСТО (NULL), функция делает копию дескриптора, но не возвращает значение продублированного дескриптора вызывающей программе. Это поведение существует только для совместимости вниз с предшествующими версиями этой функции. Вы не должны использовать эту функцию, поскольку будете терять системные ресурсы до тех пор, пока не целевой процесс не закончит свою работу.

[in] Доступ, требуемый для нового дескриптора. Перечень флажков, которые могут быть установлены для каждого типа объекта, см. в нижеследующем разделе Замечаний.

Этот параметр игнорируется, если параметр dwOptions устанавливает флажок DUPLICATE_SAME_ACCESS . Иначе, флажки, которые могут быть установлены, зависят от типа объекта, дескриптор которого должен быть продублирован.

[in] Указывает, является ли дескриптор наследуемым. Если он — ИСТИНА (TRUE), продублированный дескриптор может быть унаследован новыми процессами, созданными целевым процессом. Если он — ЛОЖЬ (FALSE), новый дескриптор не может быть унаследован.

[in] Необязательные действия. Этот параметр может быть нулевой, или любой комбинацией следующих значений.

Значение

Предназначение

DUPLICATE_CLOSE_SOURCE

Windows NT/2000/XP: Дескриптор возвращается функцией RegCreateKey , RegCreateKeyEx , RegOpenKey или RegOpenKeyEx .

Обратите внимание! те дескрипторы ключа системного реестра, возвращенные функцией RegConnectRegistry не могут быть использованы при вызове для DuplicateHandle .

Windows 95/98/Me: Вы не можете использовать DuplicateHandle , чтобы продублировать дескрипторы ключа системного реестра.

Семафор (Semaphore)

Предназначение

DUPLICATE_CLOSE_SOURCE

Windows NT/2000/XP: Дескриптор возвращается функцией RegCreateKey , RegCreateKeyEx , RegOpenKey или RegOpenKeyEx .

Обратите внимание! те дескрипторы ключа системного реестра, возвращенные функцией RegConnectRegistry не могут быть использованы при вызове для DuplicateHandle .

Windows 95/98/Me: Вы не можете использовать DuplicateHandle , чтобы продублировать дескрипторы ключа системного реестра.

Семафор (Semaphore)