Внутреннее устройство ядра Linux 2.4




Пример виртуальной файловой системы: pipefs - часть 2


В результате выполнения kern_mount():

  • Создается новое неименованное (anonymous) устройство установкой бита в unnamed_dev_in_use; если в этом массиве не окажется свободного бита, то kern_mount()

    вернется с ошибкой EMFILE.

  • Посредством get_empty_super() создается новая структура суперблока. Функция get_empty_super()

    проходит по списку суперблоков super_block в поисках свободного места, т.е. s->s_dev == 0. Если такового не обнаружилось, то резервируется память вызовом kmalloc(), с приоритетом GFP_USER. В get_empty_super() проверяется превышение максимально возможного количества суперблоков, так что в случае появления сбоев, при монтировании pipefs, можно попробовать подкорректировать /proc/sys/fs/super-max.

  • Вызывается метод pipe_fs_type->read_super()

    (т.е. pipefs_read_super()), который размещает корневой inode и dentry sb->s_root, а также записывает адрес &pipefs_ops в sb->s_op.

  • Затем вызывается add_vfsmnt(NULL, sb->s_root, "none"), которая размещает в памяти новую структуру vfsmount и включает ее в список vfsmntlist и sb->s_mounts.
  • В pipe_fs_type->kern_mnt заносится адрес новой структуры vfsmountи он же и возвращается в качестве результата. Причина, по которой возвращаемое значение является указателем на vfsmount состоит в том, что даже не смотря на флаг FS_SINGLE, файловая система может быть смонтирована несколько раз, вот только их mnt->mnt_sb будут указывать в одно и то же место.
  • После того как файловая система зарегистрирована и смонтирована, с ней можно работать. Точкой входа в файловую систему pipefs является системный вызов pipe(2), реализованный платформо-зависимой функцией sys_pipe(), которая в свою очередь передает управление платформо-независимой функции fs/pipe.c:do_pipe(). Взаимодействие do_pipe() с pipefs начинается с размещения нового inode вызовом get_pipe_inode(). В поле inode->i_sb этого inode заносится указатель на суперблок pipe_mnt->mnt_sb, в список i_fop файловых операций заносится rdwr_pipe_fops, а число "читателей" и "писателей" (содержится в inode->i_pipe) устанавливается равным 1. Причина, по которой имеется отдельное поле i_pipe, вместо хранения этой информации в приватной области fs-private, заключается в том, что каналы (pipes) и FIFO (именованные каналы) совместно используют один и тот же код, а FIFO могут существовать и в другой файловой системе, которые используют другие способы доступа в пределах этого объединения (fs-private) и могут работать, что называется "на удачу". Так, в ядре 2.2.x, все перестает работать, стоит только слегка изменить порядок следования полей в inode.

    Каждый системный вызов pipe(2) увеличивает счетчик ссылок в структуре pipe_mnt.

    В Linux каналы (pipes) не являются симметричными, т.е. с каждого конца канал имеет различный набор файловых операций file->f_op - read_pipe_fops и write_pipe_fops. При попытке записи со стороны канала, открытого на чтение, будет возвращена ошибка EBADF, то же произойдет и при попытке чтения с конца канала, открытого на запись.




    Содержание  Назад  Вперед