> man operating_systems
Создание виртуальных файловых систем в Linux
на Четверг, 25 Май 2006, 00:53
добавил: Пешеходов А. П. aka fresco список авторов печатать элемент контента создать pdf-файл  элемент контента
категория Статьи > Unix
комментарии: 1
просмотров: 4144


Создание файлов

Теперь суперблок имеет полностью работоспособныйкорневой каталог. Все реальные операции с каталогом будут обрабатываться libfs и уровнем VFS. Однако libfs не в состоянии создать что-либо интересное в корневом каталоге, и этим придется заняться нам. Перед возвратом управления функция lfs_fill_super() делает вызов lfs_create_files(), который создает и размещает логическую структуру нашей ФС. Заметим, что счетчики в нашем модуле реализованы в виде глобальных переменных типа atomic_t.

<div class='codec'>
static atomic_t counter, subcounter;

static void lfs_create_files (struct super_block *sb, struct dentry *root) {
struct dentry *subdir;

/* Создаем файл "counter" в корневом каталоге */
atomic_set(&counter, 0);
lfs_create_file(sb, root, "counter", &counter);

/* Создаем каталог "subdir" */
atomic_set(&subcounter, 0);
subdir = lfs_create_dir(sb, root, "subdir");

/* Создаем файл "subcounter" в "subdir" */
if (subdir)
lfs_create_file(sb, subdir, "subcounter", &subcounter);
}</div>

Понятно, что lfs_create_files() выполняет только инициализацию счетчиков. Реальную работу по созданию файлов и каталогов выполняют другие функции.

<div class='codec'>
static struct dentry *lfs_create_file (struct super_block *sb,
struct dentry *dir, const char *name,
atomic_t *counter) {

struct dentry *dentry;
struct inode *inode;
struct qstr qname;

/* Инициализируем qstr, считаем хэш */
qname.name = name;
qname.len = strlen (name);
qname.hash = full_name_hash(name, qname.len);

/* Создаем dentry для файла */
dentry = d_alloc(dir, &qname);
if (! dentry)
goto out;

/* Создаем inode для файла */
inode = lfs_make_inode(sb, S_IFREG | 0644);
if (! inode)
goto out_dput;
inode->i_fop = &lfs_file_ops;
inode->u.generic_ip = counter;

d_add(dentry, inode);
return dentry;

out_dput:
dput(dentry);
out:
return 0;
}</div>

В качестве аргументов эта функция принимает указатель на суперблок, dentry родительского каталога и имя создаваемого файла. Первым делом создается dentry для нового файла – вызовом d_alloc(), который принимает указатель на родительский dentry и структуру типа struct qstr, служащую для удобно представления имени файла. Эта структура, помимо самого имени и его длины, содержит также хэш, вычисляемый вызовом ful_name_hash(), по которому указанный dentry может быстро найден в кэше.

Для инициализации inode мы снова пользуемся функцией lfs_make_inode(), однако теперь мы создаем регулярный файл, о чем говорит маска S_IFREG. В inode мы используем 2 поля:
<ul>
<li>поле i_fop устанавливается указателем на структуру с файловыми операциями, реализующими чтение и запись счетчиков (lfs_file_ops). </li>
<li>поле u.generic_ip мы используем для хранения счетчика типа atomic_t. </li>
</ul>
Другими словами, i_fop определяет поведение данного конкретного файла, а u.generic_ip хранит специфичные для файла данные. Практически все виртуальные файловые системы используют эти 2 поля для установки требуемого поведения файла.

Последний этап создания файла – добавление его в dentry-кэш вызовом d_add(). Это позволяет VFS отыскивать файл без обращения к directory-операциям, онам – обойтись без реализации directory-операций. Вся наша файловая система находится внутри кэша ядра, модуль может не запоминать ее структуру и в состоянии обойтись без реализации операций просмотра (lookup) ФС. Это делает жизнь проще.

Каталог "subdir" создается функцией lfs_create_dir():

<div class='codec'>
static struct dentry *lfs_create_dir (struct super_block *sb,
struct dentry *parent, const char *name)
{
struct dentry *dentry;
struct inode *inode;
struct qstr qname;

qname.name = name;
qname.len = strlen (name);
qname.hash = full_name_hash(name, qname.len);

dentry = d_alloc(parent, &qname);
if (! dentry)
goto out;

inode = lfs_make_inode(sb, S_IFDIR | 0644);
if (! inode)
goto out_dput;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;

d_add(dentry, inode);
return dentry;

out_dput:
dput(dentry);
out:
return 0;
}</div>

Т.к. от реализации directory-операций мы отказались, поле i_fop устанавливается указателем на generic-функцию simple_dir_operations().

Создание inode

Теперь посмотрим, как работает lfs_make_inode():

<div class='codec'>
static struct inode *lfs_make_inode(struct super_block *sb, int mode) {
struct inode *ret = new_inode(sb);

if (ret) {
ret->i_mode = mode;
ret->i_uid = ret->i_gid = 0;
ret->i_blksize = PAGE_CACHE_SIZE;
ret->i_blocks = 0;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
}
return ret;
}</div>

Она просто размещает новую структуру inode (вызовом new_inode()) и заполняет ее некоторыми осмысленными значениями. Аргумент mode определяет не только права доступа к файлу, но и его тип – регулярный файл или каталог.

индекс статьи
страница 1 : страница без заголовка
страница 2 - текущая : страница без заголовка
страница 3 : страница без заголовка


© OSRC.info, 2004-2010.
Авторские права на любые материалы, авторы которых явно указаны, принадлежат их авторам. По вопросам публикации таких материалов обращайтесь к авторам.
Авторские права на любые другие материалы принадлежат OSRC.info.
Сайт является помещением библиотеки. Копирование, сохранение на жестком диске или иной способ сохранения произведений осуществляются пользователями на свой риск.
При использовании материалов сайта ссылка на OSRC.info обязательна.