最近golangでCLIツールを作っていたのだけど、Linuxのお作法とかいまいち分かっていなかった。そこでそのあたりのことが学べそうな「ふつうのLinuxプログラミング」を読んだ。

この本はLinuxにおいてC言語でプログラミングする方法を、Linuxでの重要な概念も含めて教えてくれる本。この本を読めばとりあえずC言語を使ってLinux用のプログラムを書き始めることが出来るようになりそうだった。

それでC言語を使わない場合でも役に立つの？ということだけど、非常に役立ちそうで面白かった。なぜなら、単なるプログラミングの方法を教えてくれるだけではなくて、

Linuxの重要な考え方をファイルシステム・プロセス・ストリームという概念にまとめて教えてくれる

システムコール自体の考え方や使い方を教えてくれる

からである。このあたりの概念はgolangでプログラムを書くときにも役立ちそうで、この本を読む目的を満たせて良かった。おすすめ。

この本の中で個人的に印象に残ったのは以下の二つである。

バイトストリームという考え方

Ctrl-Cでのシェルでのプロセス中断を実行する仕組み

バイトストリームという考え方 この本の中ではLinuxの概念をファイルシステム・プロセス・ストリームという言葉で教えてくれるのだけど、その中でも僕は最後のストリームという概念が非常に面白かった。この本におけるストリームとはバイトの流れる通り道のこと。他のLinuxの書籍とかではこの概念は単に「ファイル」と言われていたりするみたい。しかし、僕はストリームという言葉の方がなんとなくしっくりきた。 全てのデータの入出力は、バイトの流れる通り道であるストリームをopenし、read/writeし、closeすると考えれば様々な操作がこのストリームという概念だけで表現できることが分かる。 ファイルの読み書きは、ファイルとの間にストリームを用意し、read/writeする

キーボードの入出力は、キーボードと端末との間にストリームを用意し、キーイベントのデータをreadする

プロセス間通信は、プロセスとプロセスの間にストリームを用意し、データをread/writeする

ネットワークは、通信したい端末と端末間にストリームを用意し、read/writeする こうすることで、どのようなデータの入出力も同じopen/read/write/closeのAPIでやりとりが出来て非常にすっきりする。

Ctrl-Cでのシェルでのプロセス中断を実行する仕組み Ctrl-Cでのシェルでのプロセス中断を実行する仕組みについて解説されていたのも面白かった。Ctrl-Cを実現するためには以下のような仕組みになっている。 1. コマンドを実行すると、シェルがパイプを構成するプロセスをfork()する パイプでつながれたコマンドはそれぞれ1プロセスとしてforkされる

2. シェルがパイプのプロセスグループIDをtcsetpgrp()で端末に通知する パイプでつながれたコマンドは1つのプロセスグループIDに属する

3. forkされた各プロセスがコマンドをexecする

4. ユーザがC-cをおす

5. カーネル内の端末ドライバがそれをSIGINTに変換、動作中のプロセスグループに発送する

6. プロセスグループがデフォルトの動作に従って終了する こんな感じで、コマンド実行はすべてシェルからのforkで表現され、パイプで繋がったコマンド群がプロセスグループとして表現されることで、Ctrl-Cはそれらのプロセス全てにシグナルを送れるようになっているという感じ。単純な機能に思えるけど、その中にもいろんな仕組みが入っていて面白い。 ちなみにシェルについては最近読んだ以下の記事が非常に分かりやすかったのでおすすめ。 language-and-engineering.hatenablog.jp

