Как я могу создать файловую систему пользовательского пространства с помощью FUSE без использования libfuse?

Я обнаружил, что библиотека пользовательского пространства FUSE и интерфейс ядра были перенесены с момента их создания в Linux на многие другие системы и представляют собой относительно стабильный API с предположительно небольшой площадью поверхности. Если бы я хотел создать файловую систему в пользовательском пространстве и не был на Plan 9 или Hurd, я бы подумал, что FUSE — мой лучший выбор.

Однако я не собираюсь использовать libfuse. Это частично из-за прагматизма; использовать C сложно на моем языке (Монте). Это также потому, что я совершенно не заинтересован в написании кода поддержки C, а рекомендуемое использование libfuse несовместимо с философией Monte. Это не должно быть проблемой, так как C не является волшебным и /dev/fuse можно открыть с помощью стандартных системных вызовов.

Однако, поиграв документацию, я ничего не нашел. Я не могу найти документацию по /dev/fuse ABI/API, а также никаких историй о том, как другие идут по тому же маршруту, не связанному с C. Раздражающий.

Существует ли какая-либо документация о том, как независимо от языка взаимодействовать с /dev/fuse и подсистемой FUSE ядра? Если да, не могли бы вы указать мне на него? Спасибо!

Обновление: существует go-fuse, написанный на Go, немного более читаемом языке, чем C. Однако он не также содержать любую документацию по ABI/API.

Обновление: я заметил, что люди проголосовали за то, чтобы закрыть это. Не волнуйтесь, в этом нет необходимости. Я убедился, что документации, которую я желаю, еще не существует. Я сам напишу документацию, опубликую ее, а затем свяжусь с ней в принятом ответе. Надеюсь, следующий человек, который будет искать эту документацию, не будет разочарован.


person Corbin    schedule 24.07.2015    source источник
comment
я знаю Си; Я был здесь некоторое время (openhub.net/accounts/MostAwesomeDude). У Монте есть философия безопасности, которая означает, что большая часть существующего кода C непригодна для использования. Я рад изложить это в сообщении в блоге, если есть спрос. Что еще более важно, C не является привилегированным в своей механике. Я могу выполнять системные вызовы с любой компетентной платформы, и strace показывает мне, что libfuse делает системные вызовы. Я хочу избежать необходимости перепроектировать библиотеку с открытым исходным кодом.   -  person Corbin    schedule 24.07.2015
comment
Вам не нужно ничего перепроектировать, так как вы можете просто прочитать исходный код и документацию   -  person hek2mgl    schedule 24.07.2015
comment
Документация, на которую вы ссылаетесь, не распространяется на ABI /dev/fuse, а также на магические числа, разбросанные по всему исходному коду. (Он даже не охватывает основные исходные файлы libfuse, только пример использования!) Я понимаю, что исходный код доступен; Я читал его около 2-3 часов, прежде чем задать этот ТАК вопрос. Я не утверждаю, что отсутствие документации непреодолимо; Я утверждаю, что предпочел бы не тратить время на обратный инжиниринг того, что уже может быть где-то задокументировано.   -  person Corbin    schedule 24.07.2015
comment
Я не понимаю, как стандартный системный вызов должен быть реализован без использования C - на каком-то уровне. На самом деле monte написан на python, тогда как python написан на C. Вы действительно используете C.   -  person hek2mgl    schedule 24.07.2015
comment
Чтобы ответить на ваш запрос, системный вызов Linux выполняется путем помещения данных в регистры и создания программного прерывания; подробности см., например. en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux . Что касается Монте, я использую Typhon, написанный на RPython, который превращается в нативный исполняемый файл. Если я и собираюсь привязать себя к C FFI, то не для чего-то вроде libfuse. Как упоминалось в моем редактировании, я собираюсь просто задокументировать эту вещь и связать ее с принятым ответом, как только закончу.   -  person Corbin    schedule 24.07.2015
comment
И почему язык, который может помещать данные в регистры и создавать программные прерывания, более безопаснее, чем C?   -  person hek2mgl    schedule 25.07.2015
comment
Похоже, одна из заявленных вами целей — мобильность. Libfuse специфичен для Linux. Если вы переопределяете libfuse на каком-то другом языке, вы переопределяете библиотеку Linux. Порты Libfuse для других ОС API-совместимы с libfuse, но используют другие интерфейсы ядра. Похоже, что Go-fuse работает в Linux и Mac OS X/Darwin, но не в других ОС.   -  person n. 1.8e9-where's-my-share m.    schedule 30.07.2015


Ответы (1)


(Я не приму это, пока оно не будет завершено. Тем временем правки приветствуются!)

Основная схема сеанса FUSE:

  • open() вызывается /dev/fuse. Я назову получившийся FD управляющим FD.
  • mount() вызывается с целевой точкой монтирования, типом файловой системы «fuse» для нормального режима или «fuseblk» для режима блочного устройства и параметрами, включая «fd=X», где X — управляющий FD.
  • Структуры, специфичные для FUSE, многократно передаются в управляющем FD. Общий шаблон связи соответствует шаблону запрос-ответ, где программа read()s выполняет команды файловой системы от управляющего FD, а затем write()s отвечает обратно.
  • umount() вызывается с целевой точкой монтирования.
  • close() вызывается на управляющем FD.

С учетом всего сказанного, есть несколько осложнений, о которых следует знать. Во-первых, mount() почти всегда является привилегированным системным вызовом, поэтому для монтирования файловой системы FUSE вам понадобятся права root. Однако, как вы могли заметить, программы FUSE обычно можно запускать без полномочий root! Как?

Есть помощник, /bin/fusermount, установил setuid. Использование полностью недокументировано, но я здесь именно для этого. Вместо open()ing /dev/fuse самостоятельно запустите fusermount как подпроцесс, передав целевую точку монтирования в качестве аргумента, любые дополнительные параметры монтирования, которые вам нравятся с -o, и (что особенно важно) с экспортированной переменной среды _FUSE_COMMFD и установленной в строку ASCII открытого FD , который я назову comm FD. Вы должны сами создать comm FD, используя, например, pipe(). fusermount вызовет для вас open() и mount() и передаст вам FD управления по FD связи, используя прием sendmsg() для совместного использования FD. Используйте recvmsg(), чтобы прочитать его обратно.

Редакция: Я действительно не понимаю, почему это так сложно. FD наследуются подпроцессами; было бы намного проще open() управлять FD в верхнем процессе и передать его в fusermount. Правда, есть какие-то запутанные заместительские опасности, но fusermount уже установлен и установлен и опасен.

Так или иначе! fusermount грубо демонизируется и позаботится о вызове umount() и close() для очистки после завершения вашего основного процесса.

Вещи, которые еще не покрыты:

  • Как обрабатывается неблокирующий доступ к FUSE? Можно ли просто перевести управляющий FD в неблокирующий режим? Он на самом деле не блокируется или ведет себя как обычный файл и тайно блокирует доступ?
  • Макеты структур. Их можно более или менее заново открыть из исходников C или Go, но это не оправдание. Я задокументирую их более серьезно, когда наработаю достаточно мазохизма.
person Corbin    schedule 30.07.2015
comment
Думаю, вы уже нашли ответ. Возможно, вас заинтересует код для фьюзермаунта. read.pudn.com/ загрузки96/исходный код/unix_linux/392124/ - person webminal.org; 05.03.2016
comment
@Corbin, так что ... вы когда-нибудь получали ответ на оставшиеся вопросы, и вы действительно использовали этот подход? - person aurora; 04.05.2017
comment
Я понял, что FUSE — это не совсем то, что мне нужно. Есть разница между пользовательским и непривилегированным доступом, и я хотел последнего. С тех пор я не проводил никаких исследований по этому поводу, извините. - person Corbin; 09.05.2017