Главная страница
Навигация по странице:

  • 8.2. Нижний уровень ввода-вывода

  • 218 __ Глава 8. Интерфейс с системой UNIX

  • 222 Глава 8. Интерфейс с системой UNIX

  • 8.4. Произвольный доступ

  • 8.5. Пример. Реализация функций

  • 1116 226 Глава 8. Интерфейс с системой

  • 228 Глава 8. Интерфейс с системой

  • 8.6. Пример. Печать каталогов

  • Б. Керриган, Д. Ритчи Язык программирования C. Б. Керниган, Д. зык программирования и . Издание 3е, исправленное Перевод с английского под редакцией Вс. С. Штаркмана СанктПетербург 2003


    Скачать 31.48 Mb.
    НазваниеБ. Керниган, Д. зык программирования и . Издание 3е, исправленное Перевод с английского под редакцией Вс. С. Штаркмана СанктПетербург 2003
    АнкорБ. Керриган, Д. Ритчи Язык программирования C.pdf
    Дата06.04.2017
    Размер31.48 Mb.
    Формат файлаpdf
    Имя файлаБ. Керриган, Д. Ритчи Язык программирования C.pdf
    ТипКнига
    #4546
    страница16 из 28
    1   ...   12   13   14   15   16   17   18   19   ...   28
    Глава 8
    Интерфейс с системой UNIX
    Свои услуги операционная система UNIX предлагает в виде набора
    системных вызовов, которые фактически являются ее внутренними функ- циями и к которым можно обращаться из программ пользователя. В на- стоящей главе описано, как в Си-программах можно применять некото- рые наиболее важные вызовы. Если вы работаете в системе UNIX, то эти сведения будут вам полезны непосредственно и позволят повысить эф- фективность работы или получить доступ к тем возможностям, которых нет в библиотеке. Даже если вы используете Си в другой операционной системе, изучение рассмотренных здесь примеров все равно приблизит вас к пониманию программирования на Си; аналогичные программы (от- личающиеся лишь деталями) вы встретите практически в любой опера- ционной системе. Так как библиотека Си-программ, утвержденная в ка- честве стандарта ANSI, в основном отражает возможности системы UNIX,
    предлагаемые программы помогут вам лучше понять и библиотеку.
    Глава состоит из трех основных частей, описывающих: ввод-вывод,
    файловую систему и организацию управления памятью. В первых двух частях предполагается некоторое знакомство читателя с внешними ха- рактеристиками системы UNIX.
    . В главе 7 мы рассматривали единый для всех операционных систем ин- терфейс ввода-вывода. В любой конкретной системе программы стандарт- ной библиотеки пишутся с использованием средств именно этой кон- кретной системы. В следующих нескольких параграфах мы опишем вы- зовы системы UNIX по вводу-выводу и покажем,
    с их помощью можно реализовать некоторые разделы стандартной библиотеки.
    8.1. Дескрипторы файлов
    В системе UNIX любые операции ввода-вывода выполняются посред- ством чтения и записи файлов, поскольку все внешние устройства,

    8.2. Нижний уровень ввода-вывода (read и write) 217
    чая клавиатуру и экран, рассматриваются как файловой систе- мы. Это значит, что все связи между программой и внешними устройства- ми осуществляются в рамках единого однородного интерфейса.
    В самом общем случае, прежде чем читать или вы должны про- информировать систему о действиях, которые вы намереваетесь выпол- нять в отношении файла; эта процедура называется файла.
    Если вы собираетесь писать в файл, то, возможно, его потребуется создать заново или очистить от хранимой информации. Система проверяет ваши права на эти действия (файл существует? вы имеете к нему доступ?)
    и, если все в порядке, возвращает программе небольшое неотрицательное целое, называемое дескриптором файла. Всякий раз, когда осуществля- ется ввод-вывод, идентификация файла выполняется по его дескрипто- ру, а не по имени. (Дескриптор файла аналогичен файловому указателю,
    используемому в стандартной библиотеке, или хэндлу (handle) в MS-
    DOS.) Вся информация об открытом файле хранится и обрабатывается операционной системой; программа пользователя обращается к файлу только через его дескриптор.
    Ввод с клавиатуры и вывод на экран применяются настолько что для удобства работы ними предусмотрены специальные соглашения. При программы командный интерпретатор (shell) открывает три фай- ла с дескрипторами и 2, которые называются соответственно стандарт- ным вводом, стандартным выводом и стандартным файлом ошибок. Если программа читает из файла 0, а пишет в файлы 1 и 2 (здесь цифры - де- скрипторы файлов), то она может осуществлять ввод и вывод, не забо- тясь об их открытии.
    Пользователь программы имеет возможность перенаправить ввод-вы- вод в файл или из файла с помощью значков < и >, как, например, в prog outfile
    В этом случае командный интерпретатор заменит стандартные установ- ки дескрипторов 0 и 1 на именованные файлы. Обычно дескриптор фай- ла 2 остается подсоединенным к экрану, чтобы на него шли сообщения об ошибках. Сказанное верно и для ввода-вывода, связанного в конвейер.
    Во всех случаях замену файла осуществляет командный интерпретатор,
    а не программа. Программа, если она ссылается на файл 0 (в случае вво- да) и файлы 1 и 2 (в случае вывода), не знает, ни откуда приходит ее ввод,
    ни куда отправляется ее вывод.
    8.2. Нижний уровень ввода-вывода
    и write)
    Ввод-вывод основан на системных вызовах read и write, к которым
    Си-программа обращается с помощью функций с именами read и write.

    218 __ Глава 8. Интерфейс с системой UNIX
    Для обеих первым аргументом является дескриптор файла. Во втором ар- гументе массив символов вашей программы, куда посыла- ются или откуда берутся данные. Третий аргумент — это количество пе- ресылаемых байтов.
    n_read = read(int fd, char *buf, int n);
    int
    =
    fd, char *buf, int n);
    Обе функции возвращают число переданных байтов. При чтении чество прочитанных байтов может оказаться меньше числа, указанного в третьем аргументе. Нуль означает конец файла, а -1 сигнализирует о какой-то ошибке. При записи функция возвращает количество записан- ных байтов, и если это число не совпадает с следует считать,
    что запись не произошла.
    За один вызов можно прочитать или записать любое число байтов.
    Обычно это число равно или 1, что означает посимвольную передачу "без буферизации", или чему-нибудь вроде или 4096, соответствующих размеру физического блока внешнего устройства. Эффективнее обмени- ваться числом байтов, поскольку при этом требуется меньше системных вызовов. Используя полученные сведения, мы можем напи- сать простую программу, копирующую свой ввод на свой вывод и эквива- лентную программе копирования файла, описанной в главе
    С помощью этой программы можно копировать откуда угодно и куда угодно, посколь- ку всегда существует возможность перенаправить ввод-вывод на любой файл или устройство.
    ,
    /* копирование ввода на вывод */
    char int n;
    while
    = read(0,
    BUFSIZ)) > 0)
    write(i,
    n);
    return 0;
    Прототипы функций, обеспечивающие системные вызовы, мы собра- ли в файле h, что позволяет нам включать его в программы этой главы. Однако имя данного файла не зафиксировано стандартом.
    Параметр BUFSIZ также определен в ; в каждой конкретной системе он имеет свое значение. Если размер файла не кратен BUFSIZ,

    8.2. Нижний уровень ввода-вывода (read и write) 219
    то какая-то операция чтения вернет значение меньшее, чем BUFSIZ, а сле- дующее обращение к read даст в качестве результата нуль.
    Полезно рассмотреть, как используются read и write при написании программ более высокого уровня - таких как r, p u t c h a и. т. д. Вот,
    к примеру, версия программы getcha г, которая осуществляет небуферизо- ванный ввод, читая по одному символу из стандартного входного потока.
    /* getchar: небуферизованный ввод одного символа */
    int
    >:
    char с;
    return (read(0, &c, 1) == 1) ? (unsigned char) с : EOF;
    }
    Переменная с должна быть типа поскольку read требует указателя на
    Приведение с к unsigned перед как вернуть ее в качестве результата, исключает какие-либо проблемы, связанные с распростране- нием знака.
    Вторая версия осуществляет ввод большими кусками, но при каждом обращении выдает только один символ.
    "syscalls. h"
    *
    /* getchar: простая версия с буферизацией */
    int getchar(void)
    {
    static char static char
    = buf;
    static int n = 0;
    (n == 0) { /* буфер пуст '*/
    n = read(0, buf, sizeof buf);
    bufp =
    }
    return
    >= 0) ? (unsigned char) *bufp++ : EOF;
    }
    Если приведенные здесь версии функции getcha r компилируются с вклю- чением заголовочного файла и в этом заголовочном файле getchar определена как макрос, то нужно задать строку с именем getchar.

    220 Глава 8. Интерфейс с системой UNIX
    8.3. Системные вызовы open, creat, close, unlinc
    В отличие от стандартных файлов ввода, вывода и ошибок, которые открыты по умолчанию, остальные файлы нужно открывать явно. Для этого есть два системных вызова: open и с
    Функция open почти совпадает с open, рассмотренной в главе 7. Раз- ница между ними в том, что первая возвращает не файловый указатель,
    а дескриптор файла типа int. При любой ошибке open возвращает flinclude int fd;
    int int flags, int perms);
    fd =
    flags,
    Как и в f open, аргумент name - это строка, содержащая имя файла. Второй аргумент,
    имеет тип int и специфицирует, каким образом должен быть открыт файл. Его основными значениями являются:
    0_RDONLY - открыть только на чтение;
    - открыть только на запись;
    - открыть и на чтение, и на
    В System V UNIX эти константы определены в а в версиях
    Berkley (BCD) - в h>.
    открыть существующий файл на чтение, можно написать fd =
    0_RDONLY, 0);
    Далее везде, где мы пользуемся функцией open, ее аргумент perms равен нулю.
    Попытка открыть несуществующий файл является ошибкой.
    нового файла или перезапись старого обеспечивается системным вызо- вом
    Например int creat(char int perms);
    fd =
    Функция reat возвращает дескриптор файла, если файл создан, и если по каким-либо причинам файл создать не удалось. Если файл уже суще- с reat "обрежет" его до нулевой длины, что равносильно выбрасы- ванию предыдущего содержимого данного файла; создание уже существу- ющего файла не является ошибкой.
    Если строится действительно новый файл, то его создаст с пра- вами доступа, специфицированными в аргументе ре
    В системе UNIX
    с каждым файлом ассоциированы девять битов, содержащие информа-

    8.3. Системные вызовы open, creat, close,
    а правах пользоваться этим файлом для чтения, записи и исполне- ния лицам трех категорий: собственнику файла, определенной им группе лиц и всем остальным. Таким образом, права доступа удобно ровать с помощью трех восьмеричных цифр. Например, 0755 специфици- рует чтение, запись и право исполнения собственнику файла, а также чте- ние и право исполнения группе и всем остальным.
    Для иллюстрации приведем упрощенную версию программы ср систе- мы UNIX, которая копирует один файл в другой. В нашей версии копи- руется только один файл, не позволяется во втором аргументе указывать директорий (каталог), и права доступа не а задаются кон- стантой.
    «define PERMS 0666 /* RW для собственника, группы и остальных */
    void error(char
    /* ср: копирование f1 в
    */
    argc, char
    {
    int f1, f2, n;
    char if (argc
    3)
    ср откуда if
    = open(argv[1],
    == -1)
    error ("ср: не могу открыть файл if
    = creat(argv[2],
    == -1)
    error ("ср: не могу создать файл %s, режим argv[2], PERMS);
    while
    = read(f1, buf, BUFSIZ)) > 0)
    if buf, n)
    n)
    error ("ср: ошибка при записи в файл return 0;
    Данная программа создает файл вывода с фиксированными правами до- ступа, определяемыми кодом 0666. С помощью системного вызова stat,
    который будет описан в параграфе 8.6, мы можем определить режим ис- пользования существующего файла и задать тот же режим для копии.
    Заметим, что функция e r r o r , вызываемая с различным числом аргу- ментов, во многом похожа на р ri
    Реализация ro r иллюстрирует, как

    222 Глава 8. Интерфейс с системой UNIX
    пользоваться другими программами семейства p r i n t f . Библиотечная функция аналогична с той лишь оговоркой, что перемен- ная часть списка аргументов заменена в ней одним аргументом, который инициализируется макросом va_sta
    Подобным же образом соотносят- ся функции printf с printf и vsprintf с
    /* error: печатает сообщение об ошибке и умирает */
    void error(char
    {
    va_list
    "ошибка:
    fmt, args);
    fprintf (stderr,
    exit(1);
    }
    На количество одновременно открытых в программе файлов имеется ограничение (обычно их число колеблется около 20). Поэтому любая про- грамма, которая намеревается работать с большим количеством файлов,
    должна быть готова повторно использовать их дескрипторы. Функция close(int fd) разрывает связь между файловым дескриптором и откры- тым файлом и освобождает дескриптор для его применения с другим фай- лом. Она аналогична библиотечной функции f close с тем лишь различи- ем, что никакой очистки буфера не делает. Завершение программы с по- мощью exit или retu rn в главной программе закрывает все открытые фай- лы.
    Функция удаляет имя файла из файловой системы.
    Она соответствует функции remove стандартной библиотеки.
    Упражнение 8.1. Перепишите программу cat из главы 7, используя функции read, write, open и close. Замените ими соответствующие функ- ции стандартной библиотеки. Поэкспериментируйте, чтобы сравнить быстродействие двух версий.
    8.4. Произвольный доступ
    Ввод-вывод обычно бывает последовательным, т. е. каждая новая опе- рация имеет дело с позицией следующей за той, что

    8.4. Произвольный доступ
    223
    была в операции (чтения-записи). При однако,
    файл можно читать или производить запись в него в произвольном по- рядке. Системный вызов Iseek предоставляет способ передвигаться по файлу, не читая и не записывая данные.
    функция long lseek(int long offset, int origin);
    в файле с дескриптором f d устанавливает текущую позицию, смещая ее на величину относительно места, задаваемого значением origin. Зна- чения параметра origin или 2 означают, что на величину отсту- пают соответственно от начала, от текущей позиции или от конца файла.
    Например, если требуется добавить что-либо в файл (когда в командном интерпретаторе shell системы UNIX ввод перенаправлен оператором в файл или когда в f open задан аргумент то прежде чем что-либо за- писывать, необходимо найти конец файла с помощью вызова функции lseek(fd, OL, 2);
    Чтобы вернуться назад, в начало файла, надо выполнить lseek(fd, OL, ,0);
    Следует обратить внимание на аргумент OL: вместо OL можно было бы написать
    0 или, если функция Iseek должным образом объявлена,
    просто 0.
    Благодаря Iseek с файлами можно работать так, как будто это большие массивы, правда, с замедленным доступом. Например, следующая функ- ция читает любое число байтов из любого места файла. Она возвращает число прочитанных байтов или в случае ошибки.

    /* get: читает п байт из позиции
    */
    int fd, long pos, char *buf, int n)
    {
    if (lseek(fd, pos, 0) >= 0) /* установка позиции */
    return read(fd, buf, n);
    else return
    }
    Возвращаемое функцией Iseek значение имеет тип long и является новой позицией в файле или, в случае ошибки, равно
    Функция f seek из стан- дартной библиотеки аналогична Iseek; от последней она отличается тем,
    что в случае ошибки возвращает некоторое ненулевое значение, а ее пер- вый аргумент имеет тип

    224 Глава 8. Интерфейс с системой UNIX
    8.5. Пример. Реализация функций
    и getc
    Теперь на примере функций и getc из стандартной библиотеки покажем, как описанные выше части согласуются друг с другом.
    Напомним, что файлы в стандартной библиотеке описываются файло- выми указателями, а не дескрипторами. Указатель файла - это указатель на структуру, содержащую информацию о файле: указатель на буфер, по- зволяющий читать файл большими кусками; число незанятых байтов бу- фера; указатель на следующую позицию в буфере; дескриптор файла; флаж- ки, описывающие режим (чтение/запись), ошибочные состояния и т. д.
    Структура данных, описывающая содержится в h>, кото- рый необходимо включать (с помощью в любой исходный файл,
    если в том осуществляется стандартный ввод-вывод. Этот же заголовоч- ный файл включен и в исходные тексты библиотеки ввода-вывода.
    В следующем фрагменте, типичном для файла h>, имена, исполь- зуемые только в библиотечных функциях, начинаются с подчеркивания.
    Это сделано для того, чтобы они случайно не совпали с именами, фигу- рирующими в программе пользователя. Такое соглашение соблюдается во всех программах стандартной библиотеки.
    ;
    NULL О
    EOF (-1)
    BUFSIZ 1024 20 /* max число одновременно открытых файлов */
    typedef struct
    {
    int cnt; /* количество оставшихся символов */
    char *ptr; /* позиция следующего символа */
    char
    /* адрес буфера */
    int flag; /* режим доступа */
    int fd; /* дескриптор файла */
    } FILE;
    extern FILE
    stdin
    «define stdout stderr
    _flags {
    _READ
    /* файл открыт на чтение */
    = 02, /* файл открыт на запись */
    _UNBUF = 04, /* файл не буферизуется */

    8.5. Пример. Реализация функций
    и getc _ 225
    _EOF = 010, /* в данном файле встретился EOF */
    _ERR = 020 /* в данном файле встретилась ошибка */
    *);
    int _flushbuf(int, FILE *);
    feof(p)
    & _EOF) != 0)
    & _ERR) != 0)
    fileno(p)
    getc(p)
    >= 0 \
    ? (unsigned char) *(p)->ptr++ :
    «define
    >= 0 \
    ? *(p)->ptr++ = (x) :
    getchar() getc(stdin)
    «define putchar(x) putc((x), stdout)
    Макрос getc обычно уменьшает счетчик числа символов, находящихся в буфере, и возвращает символ, после чего приращивает указатель на еди- ницу. (Напомним, что длинные с помощью обратной наклонной черты можно продолжить на следующих строках.) Когда значение счет- чика становится отрицательным, getc вызывает _f чтобы снова за- полнить буфер, инициализировать содержимое структуры и выдать сим- вол. Типы возвращаемых символов приводятся к unsigned; это гаранти- рует, что все они будут положительными.
    Хотя в деталях ввод-вывод здесь не рассматривается, мы все же приве- ли полное определение putc. Сделано это, чтобы показать, что она дей- ствует во многом так же, как и getc, вызывая функцию когда буфер полон. В тексте имеются макросы, позволяющие получать доступ к флажкам ошибки и конца файла, а также к его дескриптору.
    Теперь можно написать функцию fopen. Большая часть инструкций относится к открытию файла, к соответствующему его позициони- рованию и к установке флажковых битов, предназначенных для индика- ции текущего состояния. Сама не отводит места для буфера; это делает _f i l l b u f при первом чтении файла.
    PERMS 0666 /*
    для собственника, группы и проч. */
    /* fopen: открывает файл,
    файловый указатель */
    FILE
    char
    1116

    226 Глава 8. Интерфейс с системой UNIX
    int fd;
    FILE *fp;
    if
    != ' &&
    != V &&
    !=
    return NULL;
    for (fp = _iob; fp <
    + OPEN_MAX; fp++)
    if
    & (_READ !
    == 0)
    break; /* найдена свободная if (fp >= _iob +
    /* нет свободной позиции */
    return NULL;
    if
    ==
    fd =
    else if
    ==
    {
    if
    =
    == -1)
    fd =
    PERMS);
    lseek(fd,
    2);
    } else fd =
    0_RDONLY, 0);
    if (fd == -1) /* невозможен доступ по имени name */
    return NULL;
    = fd;
    fp->cnt = 0;
    fp->base = NULL;
    fp->flag =
    ==
    ? _READ :
    return fp;
    }
    Приведенная здесь версия f open реализует не все режимы доступа, огово- ренные стандартом; но, мы думаем, их реализация в полном объеме не намного увеличит длину программы. Наша f open не распознает буквы сигнализирующей о бинарном вводе-выводе (поскольку в системах UNIX
    это не имеет смысла), и знака +, указывающего на возможность одновре- менно читать и писать.
    Для любого файла в момент первого обращения к нему с помощью макро- вызова getc счетчик cnt равен нулю. Следствием этого будет вызов _f
    Если выяснится, что файл на чтение не то функция _f illbuf немед- ленно возвратит EOF. В противном случае она попытается запросить память для буфера (если чтение должно быть с
    После получения области памяти для буфера _f i l l b u f обращается к read, чтобы его наполнить, устанавливает счетчик и указатели и воз- вращает первый символ из буфера. В следующих обращениях обнаружит, что память для буфера уже выделена.

    8.5. Пример. Реализация функций
    и getc 227
    /*
    запрос памяти и заполнение буфера */
    int _fillbuf(FILE *fp)
    {
    int
    _READ)
    return EOF;
    bufsize = (fp->flag &
    ? 1 : BUFSIZ;
    if (fp->base == NULL) /* буфера еще нет */
    if
    = (char *)
    == NULL)
    return EOF; /* нельзя получить буфер */
    = fp->base;
    fp->cnt = read(fp->fd, fp->ptr, bufsize);
    if
    < 0) {
    if (fp->cnt == -1)
    _EOF;
    else
    _ERR;
    fp->cnt = 0;
    return EOF;
    }
    return (unsigned char) *fp->ptr++;
    Единственное, что осталось невыясненным, - это каким образом орга- низовать начало счета. Массив _iob следует определить и инициализиро- вать так, чтобы перед тем как программа начнет работать, в нем уже была информация о файлах stdin,
    и stde rr.
    FILE
    = { /* stdin, stdout, stderr: */
    { 0, (char *) 0, (char *) 0, _READ, 0 },
    { 0, (char *) 0, (char *) 0,
    1 },
    { 0, (char
    0, (char *) 0,
    i
    2 }
    };
    Инициализация как части структуры показывает, что stdin открыт на чтение, stdout - на запись,
    - на запись без буферизации.
    Упражнение 8.2. Перепишите функции и
    работая с флаж- ками как с полями, а не с помощью явных побитовых операций. Сравните размеры и скорости двух вариантов программ.

    228 Глава 8. Интерфейс с системой UNIX
    Упражнение 8.3. Разработайте и напишите функции f flush и fclose.
    Упражнение 8.4. Функция стандартной библиотеки int fseek(FILE *fp, long offset, int origin)
    идентична функции с теми,
    отличиями, что f p - это файловый указатель, а не дескриптор, и возвращает она значение означающее состояние файла, а не позицию в нем. Напишите свою версию f seek.
    Обеспечьте, чтобы работа вашей f seek по буферизации была согласована с буферизацией, используемой другими функциями библиотеки.
    8.6. Пример. Печать каталогов
    При разного рода взаимодействиях с файловой системой иногда тре- буется получить информацию о файле, а не его содержимое. Та- кая потребность возникает, например, в программе печати каталога фай- лов, работающей аналогично команде системы UNIX. Она печатает имена файлов каталога и по желанию пользователя другую дополнитель- ную информацию (размеры, права доступа и т. д.). Аналогичной коман- дой в MS-DOS является di г.
    Так как в системе UNIX каталог - это тоже файл, функции чтобы добраться до имен файлов, нужно только его прочитать. Но чтобы полу- чить другую информацию о файле (например узнать его размер), необхо- димо выполнить системный вызов. В других системах (в MS-DOS, на- пример) системным вызовом приходится пользоваться даже для получе- ния доступа к именам файлов. Наша цель - обеспечить доступ к инфор- мации по возможности системно-независимым способом несмотря то,
    что реализация может быть существенно системно-зависима.
    Проиллюстрируем сказанное написанием программы f size. Функция f size — частный случай программы она печатает размеры всех файлов,
    перечисленных в командной строке. Если какой-либо из файлов сам яв- ляется каталогом, то, чтобы получить информацию о нем, fsize обраща- ется сама к себе. Если аргументов в командной строке нет, то обрабатыва- ется текущий каталог.
    Для начала вспомним структуру файловой системы в
    Каталог -
    это файл, содержащий список имен файлов и некоторую информацию о том, где они расположены.
    расположения" - это индекс, обеспе- чивающий доступ в другую таблицу, называемую "списком узлов
    Для каждого файла имеется свой inode, где собрана вся информация о фай-

    8.6. Пример. Печать каталогов 229
    ле, за исключением его имени. Каждый элемент каталога состоит из двух частей: из имени файла и номера узла mode.
    К сожалению, формат и точное содержимое каталога не одинаковы в разных версиях
    Поэтому, чтобы переносимую компоненту от- делить от непереносимой, разобьем нашу задачу на две. Внешний уро- вень определяет структуру, названную Oi rent, и три подпрограммы opendi г,
    и г; в результате обеспечивается системно-независимый доступ к имени и номеру узла inode каждого элемента каталога. Мы бу- дем писать программу fsize, рассчитывая на такой интерфейс, а затем покажем, как реализовать указанные функции для систем, использующих ту же структуру каталога, что и Version 7 и System V UNIX. Другие вари- анты оставим для упражнений.
    Структура Di rent содержит номер узла inode и имя. Максимальная дли- на имени файла равна
    - это значение системно-зависимо. Функ- ция opendi г возвращает указатель на структуру, названную DIR (по ана- логии с FILE), которая используется функциями readdir и closedir. Эта информация сосредоточена в заголовочном файле di h.
    tfdefine
    14 /* максимальная длина имени файла; */
    системно-зависимая величина */
    typedef struct { /* универс. структура элемента
    */
    long ino; /* номер inode */
    char
    /* имя + завершающий
    */
    }
    typedef struct { /* минимальный DIR: без буферизации и т.д. */
    int fd; /* файловый дескриптор каталога */
    Dirent d; /* элемент каталога */
    } DIR;
    DIR *opendir(char
    Dirent *readdir(DIR *dfd);
    void
    Системный вызов stat получает имя файла и возвращает полную о нем информацию, содержащуюся в узле inode, или -1 в случае ошибки. Так,
    char struct stat stbuf;
    int stat(char *, struct stat *);
    &stbuf);
    заполняет структуру stbuf информацией из узла inode о файле с именем

    230
    1   ...   12   13   14   15   16   17   18   19   ...   28


    написать администратору сайта