.TH MPU_FOPEN 3 "Август 2026" "libmpuio" "Руководство программиста LIBMPUIO" .SH ИМЯ mpu_fopen, mpu_fdopen, mpu_fclose, mpu_fflush, mpu_flushlbf, mpu_fileno \- открыть, присоединить, закрыть и синхронизировать потоки LIBMPUIO .SH ОБЗОР .nf #include mpu_FILE *mpu_fopen( const char *filename, const char *mode ); mpu_FILE *mpu_fdopen( int fd, const char *mode ); int mpu_fclose( mpu_FILE *stream ); int mpu_fflush( mpu_FILE *stream ); void mpu_flushlbf( void ); int mpu_fileno( mpu_FILE *stream ); .fi .SH ОПИСАНИЕ .B mpu_fopen открывает путь UTF-8, заданный .IR filename , используя грамматику режимов stdio ISO C. Первый символ должен быть ровно одним из: .B r (читать существующий файл), .B w (создать или усечь для записи) или .B a (при необходимости создать и добавлять каждую запись в конец). Далее, в любом порядке, может следовать не более одного .B + (update: одновременно чтение и запись) и не более одного .B b (двоичная форма записи режима). Поэтому принимаются r, rb, r+, rb+, r+b и соответствующие формы для w и a. Поскольку сырые байтовые операции LIBMPUIO и преобразование текста UTF-8 являются явными операциями, b не изменяет семантику нижележащего POSIX-дескриптора. Неизвестные, повторяющиеся или находящиеся не на своём месте символы режима отвергаются с EINVAL. .B mpu_fdopen присоединяет существующий POSIX-дескриптор. Запрошенный доступ на чтение/запись должен быть совместим с режимом доступа дескриптора. Режим добавления при необходимости включает O_APPEND. После успешного присоединения дескриптор принадлежит потоку и закрывается .BR mpu_fclose . .PP .B mpu_fflush синхронизирует поток. При NULL-аргументе функция сбрасывает все в данный момент связанные потоки, которые активно выполняют запись. Сюда входят выходные и update-потоки на основе дескрипторов и cookie, а также публикация активно записываемого потока .BR mpu_open_memstream (3). .PP .B mpu_flushlbf \- аналог расширения glibc _flushlbf() в LIBMPUIO. Функция проходит текущий глобальный список потоков и синхронизирует только те потоки, которые одновременно активно выполняют запись и настроены на построчную буферизацию MPU_IOLBF. Полностью буферизованные и небуферизованные потоки не выбираются только потому, что они доступны для записи. Ошибка не прекращает обход последующих построчно-буферизованных потоков. Поскольку интерфейс не имеет возвращаемого значения, сохраняется errno от первой неудачной синхронизации; если все выбранные синхронизации успешны, исходное значение errno вызывающей стороны сохраняется. .B mpu_fileno возвращает POSIX-дескриптор потока реального файла. Обычная форма удерживает mutex потока при чтении состояния дескриптора; mpu_fileno_unlocked() эту блокировку не выполняет. .SH ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ Функции открытия возвращают указатель на поток либо NULL. Close/flush возвращают ноль при успехе и .B mpu_EOF при ошибке. mpu_flushlbf не возвращает значения. mpu_fileno возвращает дескриптор либо -1. .PP Если при закрытии потока mpu_fclose() не удаётся записать ожидающий буферизованный вывод, mpu_fclose() всё равно закрывает и освобождает поток, но возвращает .B mpu_EOF и сохраняет errno от ошибки flush. .SH ОШИБКИ При ошибках устанавливается соответствующее .BR errno . EINVAL используется для недопустимых режимов и несовместимых операций; EBADF \- для недопустимых дескрипторов и, где применимо, потоков, не связанных с файлами. .SH БЛОКИРОВКА И ПОТОКИ ВЫПОЛНЕНИЯ Обычные функции этого семейства синхронизированы. Успешный .BR mpu_fdopen () передаёт владение дескриптором потоку; после этого приложение не должно самостоятельно закрывать дескриптор, пока поток существует. .PP .BR mpu_fclose () \- операция жизненного цикла. Код приложения обязан синхронизировать её с любым другим прямым использованием того же указателя на поток. Внутренне close и .B mpu_fflush(NULL) используют порядок блокировок «глобальный список перед потоком», поэтому обход всех потоков не может увидеть наполовину уничтоженный поток. mpu_flushlbf() использует тот же порядок. .SH БЛОКИРУЕМЫЕ И UNLOCKED-ФОРМЫ .BR mpu_fflush_unlocked () и .BR mpu_fileno_unlocked () не захватывают mutex потока. Они подходят только под явным .BR mpu_flockfile (3) или при эквивалентной внешней синхронизации. Unlocked-операций fopen, fdopen или fclose нет. .PP В отличие от .BR mpu_fflush (), unlocked flush требует поток, отличный от NULL, и никогда не означает «сбросить все потоки». .SH ПРИМЕЧАНИЯ Строки режима намеренно строги: первый символ \- r, w или a, после него не более одного + и не более одного b в любом порядке. Неизвестные, повторные или неправильно расположенные символы режима отвергаются с EINVAL. .SH СМ. ТАКЖЕ .BR libmpuio (3), .BR mpu_freopen (3), .BR mpu_tmpfile (3), .BR mpu_fmemopen (3), .BR mpu_fseek (3), .BR mpu_setvbuf (3), .BR mpu_fpurge (3) .SH ОШИБКИ СБРОСА ВСЕХ ПОТОКОВ .B mpu_fflush(NULL) пытается синхронизировать каждый связанный поток, у которого в данный момент есть ожидающий вывод. Ошибка одного потока не препятствует обработке последующих. Если один или несколько потоков завершаются ошибкой, функция возвращает .B mpu_EOF и восстанавливает .B errno от первого неудачного потока. .SH ПАРАЛЛЕЛЬНЫЕ СБРОС ВСЕХ ПОТОКОВ И ЗАКРЫТИЕ Глобальный список потоков сериализуется отдельным внутренним mutex. Его порядок блокировки определён раньше блокировки отдельного потока. mpu_fclose() удаляет поток из глобального списка, удерживая обе блокировки, и только затем начинает операцию закрытия. Поэтому параллельный mpu_fflush(NULL) видит либо полностью живой поток, либо не видит его вовсе; он не проходит по наполовину закрытому потоку и не может состязаться с уничтожением объекта потока. .PP Эта гарантия жизненного цикла относится к операциям библиотеки с глобальным списком. Она не делает допустимым произвольное параллельное использование того же указателя mpu_FILE во время или после mpu_fclose(); приложение всё равно должно синхронизировать владение явно закрываемым потоком. .SH СБРОС ВСЕХ ПОСТРОЧНО БУФЕРИЗОВАННЫХ ПОТОКОВ .B mpu_flushlbf() использует ту же дисциплину жизненного цикла глобального списка, что и mpu_fflush(NULL), но выбирает только потоки, состояние которых одновременно WRITING и MPU_IOLBF. Это полезно, когда приложению нужно опубликовать ожидающий построчно буферизованный текст, не заставляя несвязанный полностью буферизованный вывод передаваться в нижележащий backend. Операция не зависит от типа backend и потому также применяется к построчно буферизованным cookie- потокам.