ブログ記事
catやgrepを自作してOSを理解する:『ふつうのLinuxプログラミング』
OSの内部は複雑に見えるが、いくつかの軸で捉え直すと一気に見通しがよくなる。青木峰郎『ふつうのLinuxプログラミング』は、標準ライブラリの裏にあるシステムコールを直接たたきながら、Linuxの動作原理を手を動かして理解していく一冊だ。
1. catやgrepをC言語で再実装する
本書の面白さは、日々ターミナルで使っているコマンドを、自分の手でC言語から作り直していく点にある。
最も基本的なcatのクローンから始め、headやgrepへと順番に機能を広げていく。高水準のライブラリに頼るのではなく、ファイルを開き、バッファに読み込み、出力へ書き出すという動作をシステムコールのレベルで記述する。コンピュータがどうデータを動かしているかが具体的に見えてくる。引数処理やエラー処理、manで仕様を確認する一連の流れは、どの言語でも通用する自走力につながる。
2. 「ストリーム・ファイルシステム・プロセス」の3概念で繋ぐ
本書は、Linuxの内部を「ストリーム」「ファイルシステム」「プロセス」という3つの概念に絞り、全編を通してこの軸をぶらさずに解説する。
座学から実践のコーディングまで、この3つの関係を繰り返し意識させることで、バラバラだったAPIの知識が立体的に結びつく。とりわけ、通常のファイル入出力もネットワークのソケット通信も、同じ「ファイルディスクリプタ」を介した一貫したデータ処理として扱える点を、コードで確かめられる。UNIXの設計思想の一貫性が体感できる。
flowchart TD
ST["ストリーム\n(データの流れ)\nファイル・ソケット・パイプ\nすべてを統一的に扱う"] --> FD["ファイルディスクリプタ\n(整数値のハンドル)"]
FS["ファイルシステム\n(データの置き場所)\nopen() で FD を取得"] --> FD
FD --> PR["プロセス\n(実行の単位)\nfork() で複製\nexec() で別プログラムを起動"]
PR -->|"read() / write()"| ST
style ST fill:#e8f4fd,stroke:#4a9eda
style FS fill:#e8f8e8,stroke:#4caf50
style PR fill:#fff8e1,stroke:#f5a623
style FD fill:#f3e5f5,stroke:#9c27b0
3. HTTPサーバーを自作してネットワークの原点に触れる
多くのシステムプログラミング本がプロセス制御やファイルAPIで終わるなか、本書は第3部でソケットAPIを使ったHTTP/1.1サーバーの実装まで進む。
ネットワーク越しの通信の実態は、結局「あるホストのプロセス」と「別のホストのプロセス」がストリームでデータをやり取りすることだ。socket、connect、listen、acceptといったシステムコールを直接書き、接続を待ち受けて応答を返す仕組みを組み立てる。一度この経験をしておくと、普段作っているWebアプリの裏で何が起きているかを高い解像度で想像できるようになる。
こんな人に向いている
「Dockerやサーバー設定のコマンドは打てるが、OSの中で何が起きているか分からない」「システムコールという言葉は知っているが、自分のコードとの関係が掴めない」というエンジニアに最も向いている。C言語の基礎的な文法が読める前提だが、C言語の熟練者である必要はない。むしろ普段はPythonやGoなどを使っている人が「低レイヤを体験する旅」として読む使い方に合っている。
純粋に「Linuxの使い方」を学びたい目的には合わない。コマンドの使い方を覚える本ではなく、コマンドの内側を理解する本だ。既製のコマンドを使いこなしたいなら別の書を選ぶ方が効率的だが、「自分のプログラムがOSとどう対話しているか」を知りたい人には替えの効かない一冊だ。
読み合わせの提案
同じ低レイヤの視点を持つ本として、Goで同じ世界を探索する「Goならわかるシステムプログラミング」がある。こちらは現代的なGoを使って同様のテーマに踏み込む。C言語が読みにくいと感じる人や、より現代的な言語でシステム的な概念を理解したい人にはGoの方が取っつきやすいかもしれない。二冊を比べることで、言語が違ってもOSの原則は変わらないことを実感できる。
今の開発環境で活きる理由
コンテナ全盛の時代に、なぜシステムコールを学ぶのか。その理由は、Dockerコンテナもマイクロサービスも、結局はLinuxのプロセス・ファイルシステム・ネットワーク上で動いているからだ。cgroup・namespace・socket といった概念の根っこは本書が扱うシステムコールの層にある。本書を読んだあとにDockerのソースコードや障害事例を追うと、理解の深さが変わる。実務から少し離れて基礎を固めると、現場での問題解決のスピードが上がる——本書はそういう効果をもたらす一冊だ。
読み終えた後のステップ
本書でプロセス・I/O・メモリをOSがどう扱うかを手で確かめたら、次はその仕組みの上に載るフレームワークへ視点を上げると学びが繋がる。『Spring徹底入門』は、フレームワークが裏で何を肩代わりしているかを追える一冊で、低レイヤーを知った目で読むとSpringがブラックボックスでなくなり、性能問題や障害の切り分けに効いてくる。
読了後の最初の一歩としては、普段よく使うコマンドを1つ選び、man でそれが呼ぶシステムコールを確認しながら最小版を自作してみるのが手頃だ。本書がcatから始めてgrepへ機能を広げた進め方を、自分の関心のあるコマンドで反復すると、読んだ知識が自走力として定着する。
まとめ
システムプログラミングを「自分には関係ない」と遠ざけてきたエンジニアが、本書を通じて「コマンドラインの裏側」に確かな解像度を得る——その体験がこの本の最大の価値だ。抽象の上で働くプログラマーほど、低レイヤの知識が土台として効く。
筆者の体験から
Web系に転職してフルスタックを任されるようになった頃、本番障害対応で先輩に「straceやlsofで見て」と言われても何を確認すべきか分からず、言われるがままコマンドを打つ自分にもどかしさを感じていた。書店でcatやgrepを自作するという構成に惹かれて本書を手に取った。
読み終えてからは、通常のファイルもソケットも同じファイルディスクリプタとして扱われると分かり、lsofの出力を見るのが怖くなくなった。エラーで迷えばまずmanを見る癖もついた。
とはいえC言語の文法は解説されない前提のため、後輩に薦めたらポインタ操作でつまずいてしまった。第3部のHTTPサーバー自作も実務のフレームワークとは距離があり、読んだだけで低レイヤーが分かった気になるのは危うい。
読み終えてしばらくした頃、本番でtoo many open filesが発生し、lsofを叩くとcloseされないソケットがCLOSE_WAITで溜まっていた。「同じfdとして扱われる」という一文が、その場で障害と繋がった瞬間だった。
DevBookPath のマップで確認する
この本の前後の読書順は、DevBookPath のグラフで確認できます。
本記事のリンクには Amazon アソシエイト等の広告が含まれる場合があります。リンク経由の購入で運営者に紹介料が支払われることがあります。
この記事を共有
この地図を共有