Дескриптори

Дескриптор файлу - це ціле число без знаку, за допомогою якого процес звертається до відкритого файлу.

FILE

Для кожного відкритого файлу в системі створюється структура fiIe, яка описує як відкритий файл, так і операції, які процес збирається проводити з файлом

Структура file містить такі поля, як:

− ознака режиму відкриття;

− покажчик на структуру vnode;

− поточний зсув у файлі;

− лічильник посилань на дану структуру;

− покажчик на структуру, що містить права процесу, що відкрив файл (ця структура знаходиться в дескрипторі процесу);

− покажчики на попередню і подальшу структури file, що зв'язують всі такі структури в подвійний список.

 

Для потокових файлів (наприклад, каналів і сокетів) поняття зсуву не підтримується, оскільки довільний доступ до цих файлів неможливий.

Обидва об'єкти відбиваються в спеціальних системних таблицях після відкриття файлу. Таблиця відкритих файлів створюється в оперативній пам'яті під час завантаження системи. Таблиця файлових дескрипторів створюється для кожного процесу. Зв'язок між таблицями:

 

Рисунок 1. – Системні структури керування файлами

Таблиця файлових дескрипторів

Дескриптори файлів виконують роль індексів таблиці дескрипторів, яка створюється ядром для кожного процесу. При відкритті файлу в цій таблиці шукається вільний осередок, в неї заноситься посилання на структуру file.

Кожен запис такої таблиці містить два поля: поле прапорів і покажчик на структуру файл. Найчастіше процес отримує дескриптори за допомогою операцій відкриття і створення файлів, а також шляхом спадкоємства від батьківського процесу.

Програма може використовувати дескриптори файлів з номерами 0..N. N визначене в include-файле <sys/param.h>.

[Щоб набути фактичного значення числа N, можна викликати функцію sysconf з аргументом _SC_OPEN_MAX, наприклад, так:

 

printf(“_SC_OPEN_MAX = %ld\n”, sysconf(_SC_OPEN_MAX));

У операційній системі Linux 2.4 ми отримаємо число 1024, в FREEBSD — 957, в Solaris — 256.]

Дескриптори є локальними для кожної програми. Тобто якщо дві програми відкрили один і той же файл - дескриптори цього файлу в кожній з них не обов'язково співпадуть (хоча і можуть). Назад: однакові дескриптори (номери) в різних програмах не обов'язково позначають один і той же файл. Декілька або один процесів можуть відкрити один і той же файл одночасно кілька разів. При цьому буде створено декілька структур, що "пов'язують" (по одній для кожного відкриття); кожна з них матиме СВІЙ покажчик читання/запису. Можлива і ситуація, коли декілька дескрипторів посилаються до однієї структури.

 

Таблиця відкритих файлів

Система має таблицю відкритих файлів. Об'єкти цієї таблиці є покажчиками на структуру file.

При закритті файлу зв'язна структура в ядрі знищується, осередок в таблиці вважається вільним, тобто зв'язок програми і файлу розривається.

При створенні процесу йому автоматично надаються три зумовлені потоки. Ці потоки оголошені в заголовному файлі "stdio.h".

 

FILE * stdin стандартний вхідний потік, який є нормальним джерелом введення для програми.

FILE * stdout потік стандартного виводу, який використовується для нормального виведення програми.

FILE * stderr стандартний потік помилки, який використовується для повідомлень про помилки і діагностики, виданою програмою.

 

Стандартним потокам відповідають стандартні дескриптори.

0 — вхідному потоку або STDIN_FILENO

1 — вихідному потоку або STDOUT_FILENO

2 — потоку помилок або STDERR_FILENO

 

У нормальному інтерактивному режимі роботи стандартний потік введення зв'язує процес з клавіатурою, а стандартні потоки виводу і виведення помилок – з поточним терміналом.

2. Отримання даних індексного дескриптору

 

Процедура читання даних з індексного вузла прямо з файлу пристрою є занадто низкоуровневой. На щастя, для одержання інформації з індексних вузлів, існують три стандартних системних виклики - stat, lstat і fstat і одна дуже відома команда - ls.

stat — повертає відомості про файл по його ім'ю

«include <sys/stat.h>

int stat(const char *path, struct stat *buf )

 

path - повне ім'я файлу

struct stat *buf - структура, що зберігає значення індексного дескриптора файлу

Повертає 0 у випадку успіху, -1 у випадку помилки (код помилки -у змінної errno)

 

lstat — повертає відомості про файл по його ім'ю без разыменования символічних посилань

«include <sys/stat.h>

int lstat(const char*path, struct stat *buf);

 

path - повне ім'я файлу

struct stat *buf - повертається информация

Повертає 0 у випадку успіху, -1 у випадку помилки (код помилки - у змінної errno) */

 

fstat — повертає відомості про файл по дескрипторі

#include <sys/stat.h>

int fstat(const int fd, struct stat *buf);

 

fd - дескриптор файлу

struct stat *buf - повертається информация

Повертає 0 у випадку успіху, -1 у випадку помилки (код помилки - у змінної errno)

 

Системний виклик stat приймає повне ім'я файлу й знаходить відповідний йому індексний вузол. Виклик fstat приймає дескриптор відкритого файлу й відшукує відповідний індексний вузол у таблиці активних вузлів ядра. Виклик lstat аналогічний виклику stat за одним виключенням - якщо як ім'я файлу було передане символічне посилання, то буде повернута інформація про саме посилання, а не про об'єкт, що вона представляє*. Всі три виклики повертають ті самі метаданные, через структуру типу stat, у першому аргументі.

Нижче приводиться визначення структури stat. Однак у деяких реалізаціях поля структури можуть бути переставлені місцями, можуть бути додані нові поля,

 

struct stat — структура для прийому відомостей з stat, fstat і lstat

struct stat {

dev_t st_dev; ідентифікатор пристрою

ino_t st_ino; номер індексного вузла

mode_t st_mode; режими доступу, тип

nlink_t st_nlink; кіл-у твердих посилань

uid_t st_uid; ідентифікатор користувача

gid_t st_gid; ідентифікатор групи

dev_t st_rdev; ідентифікатор пристрою (для спеціального

файлу)

off_t st_size; розмір у байтах

time_t st_atime; час останнього обігу

time_t st_mtime; час останньої зміни

time_t st_ctime; час останньої зміни

blksize_t st_blksize; оптимальний розмір блоку (для операцій

уведення-висновку)

blkcnt_t st_blocks; кіл-у блоків по 512 байт

}

 

Ідентифікатор пристрою (типу dev_t) - це число, унікальне для кожної змонтованої файлової системи, навіть для NFS-Томів. Таким чином, комбінації st_dev і st_ino однозначно ідентифікують будь-який індексний вузол у системі.- властиво пристрій. Як правило, молодший номер пристрою - це самий молодший байт.

Поле st.dev - це пристрій, на якому перебуває індексний вузол. Поле st_rdev використовується тільки для спеціальних файлів пристроїв і є пристроєм, що спеціальний файл представляє.

Поле st_size інтерпретується залежно від типу файлу й реалізації. Для звичайних файлів, каталогів і символічних посилань - це обсяг даних на диску (для символічних посилань - довжина шляхи). Для об'єктів у поділюваній пам'яті - обсяг займаної пам'яті. Для каналів - кількість даних у каналі.

Поле st_blksize призначене для зміни розміру блоку файлу. У більшості випадків, імовірно, має те ж призначення, що й аналогічне поле в суперблоці.

Якщо файл має «діри», отримані як результат установки поточної позиції у файлі за його межі й наступного запису яких-небудь даних, значення st_blocks * 512 може виявитися менше значення st_size.

Системний виклик fstat особливо затребуваний у ситуаціях, коли потрібно одержати відомості про елемент, що не має шляху у файловій системі, наприклад, про неіменований канал або сокете. Для цих об'єктів поля st_mode, st_ino, st_dev, st_uid, st_gid, st_atime, st_ctime і st_mtime містять актуальні значення, але що стосується інших полів - все залежить від реалізації. Проте, для іменованих і неіменованих каналів поле st_size, як правило, містить кількість непрочитаних байт у каналі.

Поле st_ctime Час останньої зміни індексного вузла (st_ctime) іноді називається як «час останньої зміни статусу».змінюється (установлюється рівним поточного астрономічного часу) при застосуванні до файлу викликів creat, chmod, chown, link, unlink, mknod, utime*, write (тому що змінюється довжина файлу); не обновляється при читанні даних з файлу. Це поле варто розглядати як час модифікації прав доступу до файлу;

st_mtime - write, creat, mknod, utime; Це поле варто розглядати як час модифікації вмісту файлу (даних);

st_atime - read, creat, mknod, utime; Це поле варто розглядати як час читання вмісту файлу (даних).