Программирование >>  Структура ядра и системные вызовы 

1 ... 26 27 28 [ 29 ] 30 31 32 ... 98


fvar.l ien = 0;

} /* пока есть блокировки, установленные другими процессамиу*/ } /* пока попытка блокирования не будет успешной */ /* файл заблокирован; теперь обработать данные в файле */ /* ... */

/* теперь снять блокировку со всего файла */ fvar.l type = F UNLCK; fvar.l whence = SEEK SET; fvar.l start =0; fvar.l len =0;

if (fcntl(fdesc, F SEtLKW,Sfvar)==-1) perror( fcntl )

}

return 0; } /* main */

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

путевое имя файла;

идентификатор процесса, который заблокировал область;

начальный адрес заблокированной области;

длину заблокированной области;

вид блокировки: исключающая (блокировка записи) или разделяемая (блокировка чтения).

Цикл выполняется до тех пор, пока вызов функции fcntl не будет выполнен успешно. После этого программа обрабатывает файл, а затем вызовом fcntl снимает с него блокировку.

7.3. API каталогов

Файлы каталогов в UNIX- и POSIX-системах используются для того, чтобы помочь пользователям организовать свои файлы в некую структуру, соответствующую их назначению (например, все исходные тексты программы на С++ можно поместить в каталот /и$г/<имя программы>/0. Каталоги используются операционной системой также для преобразования путевых имен файлов в номера их индексных дескрипторов.

В BSD UNIX и POSIX.l катштоги создаются с помощью API mkdir.

#include <sys/stat.h> #include <uni5td.h>

int nikdir ( const char* path name, mode t mode ):

Аргумент path name - это путевое имя файла каталога, который нужно создать. Аргумент mode задает права доступа для владельца, группы и прочих пользователей, которые будут назначены этому файлу. Как и в API open, значение mode модифицируется значением umask вызывающего процесса.

В случае успешного выполнения /пМ>возвращает О, а в случае неудачи - -1. Среди возможных причин неудачи следует назвать ошибку в аргументе path name, отсутствие у вызывающего процесса права на создание указанного каталога, ошибку в аргументе mode.

В UNIX System V.3 для создания файлов каталогов используется API mknod. В UNIX System V.4 поддерживаются оба интерфейса, mkdir и mknodl Различие между ними состоит в том, что каталог, созданный функцией mknod, не содержит ссылок на текущий и родительский каталоги, поэтому его можно использовать только после того, как пользователь создаст эти ссылки явно. Одновременно с созданием каталога функцией mkdir появляются и ссылки на текущий и родительский каталоги, поэтому каталог можно использовать сразу же. Вообще-то говоря, mknod не следует применять для создания каталогов. А в системах, где не поддерживается API mkdir, каталоги можно создавать с помощью API system:

char syscmd[256];

sprintf (syscmd, mkdir %s ,<имя каталога>); if (system (syscmd) == -1) perror ( mkdir );

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

Каталог - это файл, содержащий записи, в каждой из которых хранится имя и номер индексного дескриптора файла, расположенного в этом каталоге. Структура записей каталога не во всех системах одинакова. Например, в UNIX System V записи каталога имеют фиксированную длину, а в BSD UNIX - переменную. Чтобы процесс мог просматривать каталоги независимо от файловой системы, запись каталога определена как struct dirent в заголовке <dirent.h> (в UNIX System V и POSIX.l) и как struct direct в заголовке <sys/dir.h> (в BSD UNIX 4.2 и 4.3). Типы данных struct dirent и struct direct имеют одно общее поле, d name, представляющее собой массив символов, который содержит имя файла, находящегося в каталоге. Для ускоренного просмотра каталогов созданы переносимые функции, определенные в заголовках <dirent.h> и <sys/dir.h>.



#include <sys/types.h>

#if defined (BSD) && ! POSIX SOURCE

#include <sys/dir.h>

typedef struct direct Dirent; #else

#include <dirent.h>

typedef stuct dirent Dirent; #endif

DIR* opendir (const char* path name); Dirent* readdir (DIR* dir fdesc); int dosedir (DIR* dir fdesc); void rewinddir (DIR* dir fdesc);

Использование этих функций описано ниже.

Функция Назначение

opendir Открывает файл каталога только для чтения. Возвращает указатель

на структуру DIR* для последующих обращений к файлу

readdir Читает запись из файла каталога, обозначенного аргументом

dir Jdesc, и возвращает содержащуюся в ней информацию

dosedir Закрывает файл, обозначенный аргументом dirJdesc

rewinddir Устанавливает указатель чтения в начало файла каталога, обозначенного аргументом dir Jdesc. Следующий вызов readdir прочитает первую запись из этого файла

Функция opendir аналогична API open. В качестве аргумента она принимает путевое имя файла каталога и открывает этот файл только для чтения. Данная функция возвращает указатель на структуру DIR*, которая используется приблизительно так же, как указатель на структуру FILE*, возвращаемый функцией fopen. Структура данных DIR определена в заголовке <dirent.h> или <sys/dir.h>.

Функция readdir читает следующую (относительно текущей позиции указателя) запись из файла каталога, обозначенного аргументом dirJdesc. Значение dirJdesc - это значение DIR*, возвращенное вызовом opendir Данная функция возвращает адрес записи типа struct dirent или struct direct, в которой хранится имя файла. Когда readdir вызывается после API opendir или rewinddir, она возвращает указатель на первую запись данных из файла, при следующем вызове - на вторую запись и т.д. Просмотрев все записи в файле каталога, readdir возвращает нулевое значение, показывая тем самым, что достигнут конец файла. Отметим, что тип данных Dirent определяется в вышеприведенном прототипе либо как struct dirent (для POSIX и UNIX System V), либо как struct direct (для BSD UNIX в POSIX-несовместимом режиме). Благодаря этому любое приложение, вызывающее readdir, может трактовать возвращаемое значение как Dirent независимо от системы, в которой оно работает.

Функция dosedir аналогична API close. Она закрывает соединение между указателем dir Jdesc и файлом каталога.

Функция rewinddir сбрасывает указатель чтения, связанный с файлом dir Jdesc, так, чтобы при следующем вызове readdir эта функция могла просматривать данный каталог (обозначенный аргументом dir Jdesc) с начала.

В UNIX-системах (System V и BSD UNIX) определены дополнительные функции для произвольной выборки записей файлов каталогов. Стандартом POSIX. 1 эти функции не поддерживаются.

Функция Назначение

telldir Возвращает указатель на текущую позицию в файле, заданном аргу-

ментом dirJdesc

seekdir Изменяет указатель текущей позиции в файле, заданном аргументом dir Jdesc, на указанный адрес

Удаление файлов каталогов производится с помошью API rmdir. При наличии статуса привилегированного пользователя можно удалять каталоги с помошью API unlink. Эти API требуют, чтобы удаляемые каталоги были пустыми, т.е. не содержали никаких файлов, кроме ссылок на текущий и родительский каталоги. Прототип функции rmdir выглядит следующим образом:

#include <unistd.h>

int rmdir (const char* path name);

Ниже приведена программа listdir. С, которая иллюстрирует использование API mkdir, opendir, readdir, dosedir и rmdir

♦include <iostream.h> ♦include <stdio.h>

♦ include <sys/types.T

♦ include <unistd.h> ifi : ♦include <fcntl.h> ♦include <string.h> ♦include <sys/stat.h>

♦if defined (BSD) && ! P0SIX SOURCE

♦include <sys/dir.h>

typedef struct direct Dirent; ♦else

♦include <dirent.h> typedef struct dirent Dirent; ♦endif

int main (int argc, char* argv[]) Dirent* dp;



DIR* dir fdesc; . .

while (-argc > 0) { /* вьтолнить следующее для казкдого файла */ if (! (dir fdesc=opendir(*++argv) 1 )

{

.Klif (mkdir(*argv, S IRWXUIS IRWXGIS IRWXO)==-1) , > \ perror ( opendir ) ; j.ijcontinue;

/* просмотреть каждый файл каталога дважды */

int i = 0;

for ( ; i < 2; i++)

{ -

Ints cnt = 0; .

for (; dp=readdir(dir fdesc); )

cout dp->d name endl; if (strcmp(dp->d name, . ) && strcmp(dp->d name, .. )) Gnt++; . /* подсчитать количество файлоа

в каталоге */

if (!cnt) { rmdir(*argv); break; }/* пустой каталог */ rewinddir (dir fdesc) ; /* сбросить указатель дпя второго цикла */

) -

closedir(dir fdesc> f ) /* для каждого файла */

return 0; } /* main */

В качестве аргументов эта программа принимает один или несколько путевых имен файлов каталогов. Для каждого аргумента программа выполняет указанные ниже операции. Вначале она открывает его вызовом opendir и присваивает значение указателя позиции в файле переменной dirjdesc. Если вызов opendir неудачен, программа считает, что данного каталога не существует, и пробует создать его с помощью API mkdir. Если opendir выполняется успещно, программа просматривает файл каталога с помощью API readdir и определяет число файлов в нем (без учета файлов . и .. ). Затем, если каталог пуст, программа удаляет его при помощи API rmdir. Если в каталоге есть файлы, то программа с помощью rewinddir сбрасывает указатель файла, связанный с dirjdesc, а затем просматривает каталог-вторично и выводит имена всех находящихся в нем файлов на стандартный вывод. По заверщении второго цикла просмотра каталога программа закрывает dir Jdesc с помощью API closedir.

7Л, API файлов устройств

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

ДЛЯ выполнения фактической пересылки данных. Файлы устройств бывают байт-ориентированными и блок-ориентированными.

Поддержка файлов устройств зависит от реализации ОС. В стандарте POSIX.l порядок создания файлов устройств не оговаривается. В UNIX-системах для создания файлов устройств применяется API mknod:

#include <sys/stat.h> #include <unistd.h>

int mknod (const char* path name, mode t mode, int device id);

Аргумент path name - это путевое имя файла устройства, который нужно создать. Аргумент mode задает права доступа к создаваемому файлу для владельца, группы и прочих пользователей, а также устанавливает флаги S IFCHR или S IFBLK. Флаги служат для обозначения типа файла устройства (байт-ориентированный или блок-ориентированный). Права доступа модифицируются значением umask вызывающего процесса. Наконец, аргумент deviceJd содержит старший и младший номера устройств и в большинстве UNIX-систем строится следующим образом: младший байт deviceid устанавливается равным младшему номеру устройства, а следующий байт - равным старшему номеру устройства. Например, чтобы создать блок-ориентированный файл устройства SCSI5 со старшим номером 15, младшим номером 3 и правами доступа на чтение, запись и выполнение для всех пользователей, нужно применить следующий системный вызов mknod:

mknod( SCSI5 , S IFBLK S IRWXU S IRWXG S IRWXO, (15 8)3);

В UNIX System V.4 старший и младший номера устройства расширены соответственно до 14 и 18 битов. Старший и младший номера устройства используются следующим образом. Когда процесс читает данные из файла устройства или записывает данные в этот файл, с помощью старшего номера устройства файла производится поиск и вызов драйвера устройства, который выполняет фактический обмен данными с физическим устройством. Младший номер устройства - это аргумент, передаваемый в драйвер устройства при его вызове. Он необходим потому, что драйвер устройства может применяться для устройств различных типов, и младший номер задает параметры (например, размер буфера), которые должны использоваться для организации доступа к конкретному устройству.

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

В случае успешного выполнения функция mknod возвращает О, а в случае неудачи возвращает -1. Среди возможных причин неудачи можно выделить ошибку в путевом имени, отсутствие у процесса права на создание файла устройства, ошибку в аргументе mode.



1 ... 26 27 28 [ 29 ] 30 31 32 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика