|
Программирование >> Структура ядра и системные вызовы
дескриптором файла флаг 0 NONBLOCK или 0 NDELAY. Поведение функции read с такими особыми файлами будет подробно описано в разделах, посвященных API FIFO-файлов и файлов устройств. 7.1.4. Функция write Функция write помещает блок данных фиксированного размера в файл, обозначенный соответствующим дескриптором. Ее действие противоположно действию функции read. Прототип этой функции выглядит следующим образом: #include <sys/types.h> #include <unistd.h> ssize t write { int fdesc, const void* buf, size t size ); Первый аргумент, fdesc, - это целочисленный дескриптор, обозначающий открытый файл. Второй аргумент, buf - адрес буфера, содержащего данные, которые предназначены для записи в файл. Третий аргумент, size, задает количество байтов, находящихся в аргументе buf. Как и API read, API write может работать с текстовыми и двоичными файлами. Именно по этой причине тип данных аргумента buf - >ниверсаль-ный указатель {void*). Например, представленный ниже фрагмент кода записывает десять записей данных типа struct sample в файл dbasel struct sample { int x; double y; char* z; ) varX[10]; int fd = open ( dbase2 , 0 WRONLY); /* здесь инициализировать массив varX... */ write (fd, (void*)varX, sizeof varX ); Функция write возвращает количество байтов данных, успешно записанных в файл. РСак правило, оно должно быть равно значению size. Если же в результате выполнения write размер файла превысит установленный системой лимит или если диск файловой системы переполнится, то функция write возвратит число байтов, фактически записанных до прекращения выполнения. Прерывания, вызванные сигналами, функцией write обрабатываются так же, как функцией read. Если в процессе выполнения функции write поступает какой-то сигнал и операционная система не перезапускает этот системный вызов автоматически, write может либо выдать значение -1 и установить для егто значение EINTR (как это делается в System V), либо выдать число байтов данных, записанных до прерывания сигналом. Последний вариант оговорен как обязательный стандартом POSIX.l FIPS. Как и для функции read, в UNIX System V.4 пользователь может для каждого сигнала указать, должно ли ядро перезапускать прерываемый этим сигналом системный вызов. Таким образом, с перезапускаемыми вызовами функция write может вести себя так, как в BSD UNIX (и возвращать такое же значение, как при нормальном выполнении), а с неперезапускаемыми - так, как в UNIX System V.3 или POSIX.l FIPS. И, наконец, функция write может выполнять неблокирующую операцию, если для аргумента fdesc установлен флаг 0 NONBLOCK или 0 NDELAY. В этом она идентична функции read. 7.1.5. Функция close Функция close отсоединяет файл от процесса. Прототип этой функции представлен ниже: #include <unistd.h> int close { int fdesc ); Аргумент fdesc - это целочисленный дескриптор, обозначающий открытый файл. В случае успешного выполнения функция close возвращает О, в случае неудачи возвращает -1, а errno устанавливается в код ошибки. Функция close освобождает неиспользуемые дескрипторы файлов, чтобы их можно было задействовать для обозначения других файлов. Это весьма важно, поскольку процесс одновременно может открыть до OPEN MAX файлов, а функция close позволяет ему, многократно используя дескрипторы файлов, обращаться в ходе выполнения к большему, чем OPEN MAX, числу файлов. Кроме того, функция close освобождает ресурсы системы (например, элементы таблицы файлов и буфер, выделенные для хранения прочитанных из файла и записанных в буфер данных), которые предназначены для поддержки функционирования дескрипторов файлов. Это сокращает потребность процесса в памяти. Если процесс завершается, не закрыв все открытые файлы, ядро само их закрывает. В классе iostream определяется функция-член close, которая закрывает файл, связанный с объектом потока ввода-вывода. Эта функция-член может быть реализована с помощью API close следующим образом: ♦include <iostream.h> tinclude <sys/types.h> ♦include <unistd.h> int iostream::close{) {return close(this->fileno());) 7.1.6. Функция fcnti функция/сяг/ помогает пользователю запрашивать и устанавливать флаги управления доступом и флаг close-on-exec любого дескриптора файла. Кроме того, с помощью этой функции пользователи для обозначения одного файла могут назначать несколько дескрипторов. Прототип этой функции: #include <fcntl.h> int fcntl ( int fdesc, int cmd, ... ); Аргумент cmd задает операции, которые необходимо выполнить над файлом, обозначенным аргументом fdesc. Третий аргумент, который может быть указан после cmd, зависит от значения cmd. Возможные значения аргумента cmd, определенные в заголовке <fcntl.h>, перечислены ниже. Значение cmd Использование F GETFL Возвращает флаги управления доступом дескриптора файла fdesc F SETFL Устанавливает и сбрасывает флаги управления доступом, ко- торые заданы в третьем аргументе функции fcntl. Возможные флаги управления доступом - 0 APPEND и 0 NONBLOCK (в POSIX-совместимых UNIX-системах - 0 NDELAY) F GETFD Возвращает флаг close-on-exec файла, обозначенного аргумен- том fdesc. Если возвращаемое значение равно О, то флаг сбрасывается; в противном случае возвращается ненулевое значение и флаг устанавливается. По умолчанию для вновь открываемого файла флаг close-on-exec сброщен F SETFD Устанавливает и сбрасывает флаг close-on-exec дескриптора файла fdesc. Третий аргумент функции fcntl - целочисленное значение. При сбросе флага оно должно бьпь равно О, при установке - I F DUPFD Дублирует дескриптор файла fdesc другим дескриптором. Тре- тий аргумент функции fcntl - целочисленное значение, свидетельствующее о том, что дубликат дескриптора должен бьпь больше этого значения или равен ему. В данном случае fend возвращает дескриптор-дубликат Функция/сл используется для изменения флага управления доступом к дескриптору файла. Например, если файл открыт для блокирующего доступа в режиме чтения и записи, а процессу нужно изменить режим доступа на неблокирующую запись с добавлением, он может вызвать/сл с дескриптором этого файла: int cur flags = fcntl(fdesc, F GETFL); int rc = fcntl(fdesc, F SETFL, cur flag I 0 APPEND 0 NONBLOCK); Флаг close-on-exec дескриптора файла означает, что если процесс-владелец данного дескригтгора вызывает API exec для выполнения другой программы, этот дескриптор должен быть закрыт ядром до запуска новой программы (если флаг установлен) или не должен (если флаг сброшен). Более подробно API exec и флаг close-on-exec рассматриваются в главе 8. В приведенном ниже примере программа сообщает состояние флага close-on-exec дескриптора файла fdesc и устанавливает его: cout fdesc close-on-exec: fcntl(fdesc, F GETFD) endl; (void)fcntl(fdesc, F SETFD, 1); установить флаг close-on-exec С помощью функции fcntl можно дублировать дескриптор файла fdesc другим дескриггтором. В результате получаются два дескригттора, обозначающих один и тот же файл, с одинаковым режимом доступа (чтение и/или запись, блокирующий или неблокирующий и т.д.), совместно использующих для чтения и записи файла один указатель. Это полезно при переназначении стандартного ввода и вывода на файл. Например, следующие операторы переназначают стандартный ввод процесса на файл с именем F00: int fdesc = open( FOO , 0 RDONLY); открыть FOO для чтения close (0); закрыть стандартный ввод if (fcntl(fdesc,F DUPFD, 0)==-l) perror( fcntl ); с этого момента стандартный ввод осуществляется из файла char buf[256]; int rc = read(0,buf,26); читать данные из FOO UNIX-функции dup и dup2 выполняют ту же задачу дублирования файловых дескригтгоров, что и fcntl. Их можно реализовать с помощью fcntl следующим образом: #d€fine dup(fdesc) ♦define dup2(fdescl. fcntl(fdesc,F DUPFD,0) fd2) close(fd2), fcntl(fdesc,F DUPFD,fd2) Функция dup дублирует дескриптор файла fdesc наименьшим из неиспользуемых дескрипторов вызывающего процесса. Функция dup2 дублирует дескригттор файла fdesc с помощью дескриптора fd2 независимо от того, используется он для обозначения другого файла или нет. Дублирование файлов и переназначение стандартного ввода-вывода более подробно описаны в следующей главе. Значение, возвращаемое функцией fcntl, зависит от значения cmd, но в случае неудачи оно всегда равно -i. Неудачное выполнение может быть связано с ошибками, возникающими при задании fdesc и cmd. 7.1.7. Функция Iseek Системные вызовы read и write всегда выполняются относительно текущей позиции указателя чтения-записи в файле. С помощью системного вызова Iseek значение текущей позиции можно изменить. Таким образом, функция Iseek позволяет процессу произвольно выбирать данные из любого открытого файла. При этом она неприменима к FIFO-файлам, байт-ориентированным файлам устройств и символическим ссылкам. Прототип этой функции: #include <sys/types.h> #include <unistd.h> off t Iseek ( int fdesc, off t pos, Int whence ); Первый аргумент, fdesc, - это целочисленный дескриптор, обозначающий открытый файл. Второй аргумент, pos, задает смещение в байтах, которое должно быть прибавлено к базовому адресу для получения нового значения смещения. Базовый адрес задается аргументом v/hence, который может иметь одно из следующих значений:
Значения SEEK CUR, SEEK SET и SEEK END определяются в заголовке <unistd.h>. Следует помнить, что если значение whence равно SEEKSET, то задавать отрицательное значение pos не разрешается, так как функция в этом случае назначит отрицательное смещение в файле. Если выполнение вызова Iseek дает в результате новое смещение, выходящее за текущий признак конца файла, возможны два варианта: если файл открыт только для чтения, Iseek выдает сообщение об ошибке; если файл открыт для записи, Iseek выполняется успешно и увеличивает размер файла до значения, равного SEEK SET. Данные, находящиеся между концом файла и новым относительным адресом, инициализируются символами NULL. Функция Iseek возвращает новый относительный адрес, по которому будет выполняться следующая операция чтения или записи. В случае неудачи возвращается -L В классе iostream определены функции tellg и seekg, позволяющие произвольно выбирать данные из любого объекта потока ввода-вывода. Их можно реализовать с помощью API Iseek. Это будет выглядеть так: ##include <iostream.h> finclude <sys/types.h> include <unistd.h> streampos iostream::tellg() return (strean45os)Iseek(this->fileno(), (off t)0, SEEK CUR ); iostream&iostream::seekg(streampos pos, seek dir ref loc ) { ; if (ref loc == ios::beg ) (void)lseek(this->fileno(), else if ( ref loc == ios::cur (void) Iseek (this->fileno 0 , (off t)pos, SEEK CUR)F else if ( ref loc == ios::end ) Ж; (void)Iseek(this->fileno0, (off t)pos, SEEK END); return *this; (off Upos, SEEK SET);, функция iostream:-.tellg дает Iseek указание возвратить текущий указатель на файл, связанный с объектом потока ввода-вывода. Файловый дескриптор объекта потока ввода-вывода выдается функцией-членом fUeno. Отметим, что streampos и offj являются данными того же типа, что и long. Функция iostream::seekg смещает с помощью Iseek указатель в файле, связанном с объектом потока ввода-вывода. Аргументы iostream:-.seekg - это смещение в файле и базовый адрес. Между значениями seekjdirvi значениями whence, которые используются функцией Iseek, существует полное соответ-
Таким образом, функция iostream::seekg просто преобразует значение seekjdir в значение lseek whence и с помощью вызова Iseek смещает указатель в файловом объекте потока ввода-вывода в соответствии со значением pos. Файловый дескриптор потока ввода-вывода возвращается функцией-членом fileno. 7.1.8. Функция link , Функция link создает новую ссылку на существующий файл. Новый файл при этом не создается, а формируется лишь новое путевое имя для уже существующего файла. Вот прототип функции link: #include <unistd.h> int link { const char* curjink, const char* newjink ); Первый аргумент, curjink, - это путевое имя существующего файла, второй аргумент, newjink, - это новое путевое имя, которое должно быть присвоено этому же файлу. Если вызов выполняется успешно, то счетчик жестких ссылок файла увеличивается на единицу.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |