Slide 1

Slide 1 text

PHP でファイルシステムを作ろう 五⼗嵐 進⼠ / sji / sj-i / @sji_ch

Slide 2

Slide 2 text

⾃⼰紹介 @sji_ch SNS 上でのアイコンは GitHub が⾃動⽣成した奴

Slide 3

Slide 3 text

⽣まれも育ちも仙台

Slide 4

Slide 4 text

PHP カンファレンス仙台とかやった

Slide 5

Slide 5 text

ふつうのサラリーマン 株式会社インフィニットループ仙台⽀社所属 スマホゲーのサーバサイドプログラマ

Slide 6

Slide 6 text

⼀昨年娘ができた かわいい 絵本好き

Slide 7

Slide 7 text

Agenda ファイルシステムとは FUSE とは PHP で FUSE を利⽤する実例

Slide 8

Slide 8 text

ファイルシステム

Slide 9

Slide 9 text

ファイルシステムってこういうやつ

Slide 10

Slide 10 text

ファイル コンピュータで扱う⼀まとまりのデータ ⽤途に合わせて⾊々なのを沢⼭使う

Slide 11

Slide 11 text

⼈間はへっぽこ→分類整理が要る ⼈間の脳容量は有限 沢⼭ファイルあるとわけわかに ディレクトリ(フォルダ)で分類整理

Slide 12

Slide 12 text

⼊れ⼦にして整理できる

Slide 13

Slide 13 text

このへんのふわっとした仕組み全体=ファイルシステム コンピュータ上でファイルをどう扱うか 何をファイルとして扱うか どういう仕組みで管理するか 通常は OS がアプリケーションに提供

Slide 14

Slide 14 text

余談︓任意階層のファイルシステムは Multics 由来︖ https://softwareengineering.stackexchange.com/questions/103487/what-was-the- rst-hierarchical- le-system

Slide 15

Slide 15 text

雑談︓元を辿ればアインシュタインのしわざ︖ Peter Neumann さんが Multics のファイルシステムを設計 「アインシュタインとは2時間以上に渡り⾯会し<中略>こ の会話がきっかけとなって、私は階層的な抽象化やその他の 形の抽象化に⽣涯魅了されるようになりました」 http://www.csl.sri.com/users/neumann/

Slide 16

Slide 16 text

無駄話︓Multi → Uni https://ja.wikipedia.org/wiki/Unixの歴史

Slide 17

Slide 17 text

OS と ファイルシステム

Slide 18

Slide 18 text

仮想ファイルシステムと具体的なファイルシステム

Slide 19

Slide 19 text

ファイルシステムと⼀⼝に⾔ってもですよ どういう記憶媒体をどう利⽤してファイルやディレクトリ階層を表現するか ファイルやディレクトリへのアクセス権をどうする シンボリックリンクやハードリンク、ロックといった機構をどうする ファイルの破損に備えたデータの冗⻑化やジャーナリングの仕組みもどうしよう 各⽅式の間にトレードオフ 最適な仕組みは状況により異なる

Slide 20

Slide 20 text

仮想ファイルシステム アプリケーションがファイルを扱う際のインターフェースを抽象化して提供 アクセス先に応じ具体的なファイルシステム実装が切り替わる 1 つのアプリケーションコードで⾊々な仕組みに対応できる

Slide 21

Slide 21 text

これアレだよね、制御の反転て奴では︖︖︖ 具体的なファイルシステム(FAT とか EXT-4 とか)へのアク セス処理が、VFS のインターフェースを実装 アプリケーションからの扱いが統⼀できる カーネル的な扱いも⼀部統⼀できる

Slide 22

Slide 22 text

しかしカーネルモードのプログラムを作るのはむずい

Slide 23

Slide 23 text

もうわりと修羅の世界 カーネルと同じ権限でプログラムが動作 つまりちょっとした不具合でシステム全体がクラッシュ クラッシュしたらマシンの再起動が必要 セキュリティ的なリスクも勿論上がる

Slide 24

Slide 24 text

OS よく分かりません OS はアプリケーションを楽に作って動かすためのもの アプリケーションプログラマに対して低レベルの実装詳細を隠蔽 多くのアプリケーションプログラマーは OS 内部の機構をよく知らない

Slide 25

Slide 25 text

そしてカーネルといえばネイティブコード

Slide 26

Slide 26 text

何もかもアプリケーションと違う︕怖い︕

Slide 27

Slide 27 text

ここで FUSE ですよ

Slide 28

Slide 28 text

Filesystem in USEr space ですよ

Slide 29

Slide 29 text

FUSE は(雑に分けたら) 2 パート libfuse libc libc FUSE Ext3 ... VFS ls -l /tmp/fuse ./hello /tmp/fuse Kernel Userspace NFS CC BY SA 3.0 Unported ( ) FUSE structure.svg ( ) User:Sven@Wikipedia ( ) https://creativecommons.org/licenses/by-sa/3.0/deed.en https://commons.wikimedia.org/wiki/File:FUSE_structure.svg https://commons.wikimedia.org/wiki/User:Sven

Slide 30

Slide 30 text

C の関数呼べばファイルシステムが作れるよ︕

Slide 31

Slide 31 text

つまり C を使わなくてもいいってことだよ︕ Python: Ruby: Rust: Go: https://github.com/libfuse/python-fuse https://github.com/lwoggardner/rfusefs https://github.com/zargony/fuse-rs https://github.com/hanwen/go-fuse

Slide 32

Slide 32 text

利⽤例は⾊々 SSHFS: s3fs: Docker Desktop: https://github.com/libfuse/sshfs https://github.com/s3fs-fuse/s3fs-fuse https://www.docker.com/blog/new- lesharing-implementation-in-docker-desktop-windows/

Slide 33

Slide 33 text

Linux 以外でもいけるよ︕

Slide 34

Slide 34 text

dokany (Windows) Windows 上で動くユーザモードでのファイルシステム作成⽤ライブラリ Linux の FUSE 互換のラッパーライブラリを持つ 元々は未踏ユースで淺川浩紀さんという⼈が dokan というのを作っていた dokan の fork の dokanx の fork で今も更新されてるのが dokany https://github.com/dokan-dev/dokany

Slide 35

Slide 35 text

macFUSE (Mac OS X) Mac 版の FUSE Linux の FUSE の API のスーパーセットを提供 Linux ⽤の FUSE 実装がわりと簡単に移植できる https://osxfuse.github.io/

Slide 36

Slide 36 text

PHP で FUSE を叩く

Slide 37

Slide 37 text

sj-i/php-fuse https://github.com/sj-i/php-fuse

Slide 38

Slide 38 text

あなたと FUSE, 今すぐダウンロー ド composer require sj-i/php-fuse

Slide 39

Slide 39 text

備考: PHP 5 ⽤だと C 拡張もあったよ https://github.com/gree/php-fuse

Slide 40

Slide 40 text

API 紹介

Slide 41

Slide 41 text

そもそもの VFS の話 アプリケーションがファイルアクセス⽤のシステムコールを 呼び出す open とか read とか write とか VFS はアクセス先に応じ使うファイルシステム実装を振り分 け

Slide 42

Slide 42 text

FUSE では OS とユーザプロセスが通信 あらためてさっきの図 libfuse libc libc FUSE Ext3 ... VFS ls -l /tmp/fuse ./hello /tmp/fuse Kernel Userspace NFS CC BY SA 3.0 Unported (https://creativecommons.org/licenses/by-sa/3.0/deed.en) FUSE structure.svg (https://commons.wikimedia.org/wiki/File:FUSE_structure.svg) User:Sven@Wikipedia (https://commons.wikimedia.org/wiki/User:Sven) FUSE では VFS の処理振り分け先がユーザプロセスと通信 相⼿は FUSE の C ライブラリを使って作られたデーモン VFS からの open とか read とかの要求へ応答する

Slide 43

Slide 43 text

実際の C のコード fuse_operations という構造体へ open や read 等のコールバックを登録 fuse_operations を fuse_main() へ渡すとカーネル側からの通信を待つループに

Slide 44

Slide 44 text

PHP から FFI でも基本は⼀緒

Slide 45

Slide 45 text

⽣の FFI が使い勝⼿びみょいので PHP 側でラッパー⽤意

Slide 46

Slide 46 text

たとえば、CData を避ける FFI で C の構造体へアクセスする際には \FFI\CData を通す \stdClass ばりに型としては何もない奴 実⾏時 C の構造体のメンバが全部 \FFI\CData のインスタン スの動的プロパティとして⼊る IDE や静的解析などによる型の⽀援を殆ど受けられない

Slide 47

Slide 47 text

そうだラップしよう︕ fuse_operations と同じメンバを定義したクラスを⽤意 CData の fuse_operations を⽣成してメンバの中⾝を詰めら れるメソッドを持つ 各メンバには psalm の callable ⽤型アノーテーションを付け る

Slide 48

Slide 48 text

間違ったシグネチャは静的に怒られるよ︕

Slide 49

Slide 49 text

でもやっぱり IDE の補完も欲しいよ︕

Slide 50

Slide 50 text

オブジェクト指向ってやつでなんとかして︕ FuseOperations を取り出せるインターフェースとして、 Mountable を⽤意 FuseOperations ⾃体も Mountable の実装、$this を返すだけ

Slide 51

Slide 51 text

マウントをとりまくろう︕ Mounter を⽤意 Mountable をとって指定されたパスへマウントする

Slide 52

Slide 52 text

ザ・リッチインターフェース FilesystemInterface を⽤意 Mountable を継承 fuse_operations へ詰めるコールバックと同じシグネチャのメ ソッドを全て持つ 50 メソッドくらいある

Slide 53

Slide 53 text

めっちゃ補完される嬉しい

Slide 54

Slide 54 text

余計な⼿間は trait で誤魔化す fuse_operations は使うコールバックだけ詰めれば良い FilesystemInterface の全メソッド実装は⼤変 デフォルト実装を埋めるだけの trait を定義 メソッドの実装がこのデフォルト trait に由来するものの場合 fuse_operations に詰めない(Re ection で気合判定)

Slide 55

Slide 55 text

数メソッド実装すればファイルシステムが作れる︕

Slide 56

Slide 56 text

FS の実装例

Slide 57

Slide 57 text

何か PHP らしいのをファイルシステムにしたい

Slide 58

Slide 58 text

php-variable-fs (PHP といえば連想配列だよね︕) 連想配列とかオブジェクトは⼊れ⼦にできる 階層構造を持つデータということは⽐較的ファイルシステム 向き(︖) ライブラリとして composer install できる https://github.com/sj-i/php-variable-fs

Slide 59

Slide 59 text

var_dump みたいなノリで変数をマウントしよう︕ 連想配列をマウントした時点でプログラムの実⾏が停⽌ OS からのファイルアクセス⽤通信を待ち受ける状態に

Slide 60

Slide 60 text

もちろん phpstorm からも開けるよ︕ファイルだからね︕

Slide 61

Slide 61 text

wordpress-fs (PHP といえば WordPress だよね︕) WordPress の記事データをファイルシステムへマウント https://github.com/sj-i/wpfs

Slide 62

Slide 62 text

めんどくさいから細かいところは省くよ︕ WordPress の記事データはタクソノミーで階層化して⾒れる タクソノミーをディレクトリ扱いするとよさそう なのだが、準備時間の都合で今回は割愛 ID と slug にもとづいたファイル名でずらっと記事データを並べる

Slide 63

Slide 63 text

脱線︓PHP 以外はみんな WordPress をマウントしてるよ︕ https://github.com/abhiyerra/wpfs https://github.com/kmbt/wpmount

Slide 64

Slide 64 text

昨今はもう猫も杓⼦も Eloquent https://github.com/corcel/corcel

Slide 65

Slide 65 text

phpstorm で記事が読み書きできるよ︕

Slide 66

Slide 66 text

WordPress implements Filesystem ファイルなので grep 記事データを検索できる ファイルなので sed で⼀括置き換えが可能 ファイルなので phpstorm から記事データを開ける ファイル操作をする全てのツールが WordPress の記事データへのアクセスに使える

Slide 67

Slide 67 text

まとめ

Slide 68

Slide 68 text

ね、簡単でしょう︖(実際に)

Slide 69

Slide 69 text

かんたん(FUSE) × カンタン(FFI) = 超簡単︕

Slide 70

Slide 70 text

すべてが F(ilesystem) になる

Slide 71

Slide 71 text

全てをマウントする⾔語、PHP

Slide 72

Slide 72 text

おしまい