Skip to content
Artwork for 八百万のOSS
八百万のOSS · September 8 · 1 hr 2 min

#19 lsが返ってこない!libcの壁をgetdents64で突破した自作lls

lsは万能だと思っていませんか?実は数千万ファイルが入ったディレクトリでは、lsもrsyncも歯が立たなくなります。今回はcatatsuyがその壁を突破するために作ったGo製CLI「lls」を紹介。かつてオンプレのファイルサーバーに眠っていた3100万ファイルのリストを出し切り、AWSへの移行を可能にした自作ツールの中身を、hentekoが「なぜlsを再実装したのか」から順番に解きほぐしていきます。 前半はllsに近づくための遠回り。システムコールとは何か、なぜCはlibcを介して呼ぶのか、glibcとmusl libcの違い、Goがlibcのレイヤーごと再実装している話、Goのブートストラップ問題(1.4はCで書かれた最後のGo)、そしてCの配列とGoの配列とスライスの違いまで、システムプログラミングの土台を丁寧に積み上げます。後半でようやく本題。libcのreaddirはgetdents64を小さなバッファで何度も呼ぶため終わらないこと、llsはgetdents64を直接呼び出して5MBのバッファで読み切ること、inode番号0のエントリや「.」「..」の扱い、Cの終端文字をGoの文字列に変換する処理など、実装の勘所を具体的に語ります。さらにCとGoのエラー処理の違い(errnoと多値返却)、getdents64がLinux専用ゆえの開発の不便さも。 「readdirにバッファサイズを渡せればこんなことしなくて済んだのに」というcatatsuyの嘆きと、Hacker Newsに初投稿した顛末も聞きどころ。低レイヤーは自分に関係ないと思っているWebエンジニアにこそ聞いてほしい回です。 ## 関連リンク - lls(catatsuy): https://github.com/catatsuy/lls - ファイルが多すぎてlsが打てなくなったディレクトリでファイル名のリストを出すllsを作りました(Zenn): https://zenn.dev/catatsuy/articles/e5f3bc7944f9fe - llsとcachectlから学ぶ、Goでシステムプログラミングをする方法(Zenn): https://zenn.dev/catatsuy/articles/e15714f8e253d8 - 旧ストレージ廃止大作戦−2900万超のファイルリストを取得する(PR TIMES 開発者ブログ): https://developers.prtimes.com/2021/09/15/decommissioning_old_storage_list_a_dir_29million/ - You can list a directory containing 8 million files! But not with ls: http://be-n.com/spw/you-can-list-a-million-files-in-a-directory-but-not-with-ls.html - Hacker News(上記記事のスレッド): https://news.ycombinator.com/item?id=28191639 - Show HN: lls(catatsuyの投稿): https://news.ycombinator.com/item?id=28344386 - getdents(2) man page: https://man7.org/linux/man-pages/man2/getdents.2.html - readdir(3) man page: https://man7.org/linux/man-pages/man3/readdir.3.html - open(2) man page: https://man7.org/linux/man-pages/man2/open.2.html - Go syscall パッケージ: https://pkg.go.dev/syscall - golang.org/x/sys/unix: https://pkg.go.dev/golang.org/x/sys/unix - Go のソースからのビルド(ブートストラップ): https://go.dev/doc/install/source - Go Slices: usage and internals: https://go.dev/blog/slices-intro - GNU C Library (glibc): https://www.gnu.org/software/libc/ - musl libc: https://musl.libc.org/ - Alpine Linux: https://alpinelinux.org/ ───────────── YouTube: https://youtu.be/WWZdM-it9t4 Web: https://yaoyorozu-oss.henteko07.com/ X: https://x.com/yaoyorozu_oss

0:00-1:02:55

transcript

No transcript — this publisher did not publish one.

show notes

lsは万能だと思っていませんか?実は数千万ファイルが入ったディレクトリでは、lsもrsyncも歯が立たなくなります。今回はcatatsuyがその壁を突破するために作ったGo製CLI「lls」を紹介。かつてオンプレのファイルサーバーに眠っていた3100万ファイルのリストを出し切り、AWSへの移行を可能にした自作ツールの中身を、hentekoが「なぜlsを再実装したのか」から順番に解きほぐしていきます。


前半はllsに近づくための遠回り。システムコールとは何か、なぜCはlibcを介して呼ぶのか、glibcとmusl libcの違い、Goがlibcのレイヤーごと再実装している話、Goのブートストラップ問題(1.4はCで書かれた最後のGo)、そしてCの配列とGoの配列とスライスの違いまで、システムプログラミングの土台を丁寧に積み上げます。後半でようやく本題。libcのreaddirはgetdents64を小さなバッファで何度も呼ぶため終わらないこと、llsはgetdents64を直接呼び出して5MBのバッファで読み切ること、inode番号0のエントリや「.」「..」の扱い、Cの終端文字をGoの文字列に変換する処理など、実装の勘所を具体的に語ります。さらにCとGoのエラー処理の違い(errnoと多値返却)、getdents64がLinux専用ゆえの開発の不便さも。


「readdirにバッファサイズを渡せればこんなことしなくて済んだのに」というcatatsuyの嘆きと、Hacker Newsに初投稿した顛末も聞きどころ。低レイヤーは自分に関係ないと思っているWebエンジニアにこそ聞いてほしい回です。


## 関連リンク

- lls(catatsuy): https://github.com/catatsuy/lls

- ファイルが多すぎてlsが打てなくなったディレクトリでファイル名のリストを出すllsを作りました(Zenn): https://zenn.dev/catatsuy/articles/e5f3bc7944f9fe

- llsとcachectlから学ぶ、Goでシステムプログラミングをする方法(Zenn): https://zenn.dev/catatsuy/articles/e15714f8e253d8

- 旧ストレージ廃止大作戦−2900万超のファイルリストを取得する(PR TIMES 開発者ブログ): https://developers.prtimes.com/2021/09/15/decommissioning_old_storage_list_a_dir_29million/

- You can list a directory containing 8 million files! But not with ls: http://be-n.com/spw/you-can-list-a-million-files-in-a-directory-but-not-with-ls.html

- Hacker News(上記記事のスレッド): https://news.ycombinator.com/item?id=28191639

- Show HN: lls(catatsuyの投稿): https://news.ycombinator.com/item?id=28344386

- getdents(2) man page: https://man7.org/linux/man-pages/man2/getdents.2.html

- readdir(3) man page: https://man7.org/linux/man-pages/man3/readdir.3.html

- open(2) man page: https://man7.org/linux/man-pages/man2/open.2.html

- Go syscall パッケージ: https://pkg.go.dev/syscall

- golang.org/x/sys/unix: https://pkg.go.dev/golang.org/x/sys/unix

- Go のソースからのビルド(ブートストラップ): https://go.dev/doc/install/source

- Go Slices: usage and internals: https://go.dev/blog/slices-intro

- GNU C Library (glibc): https://www.gnu.org/software/libc/

- musl libc: https://musl.libc.org/

- Alpine Linux: https://alpinelinux.org/


─────────────

YouTube: https://youtu.be/WWZdM-it9t4

Web: https://yaoyorozu-oss.henteko07.com/

X: https://x.com/yaoyorozu_oss