📝

TIL: UNIXプログラミング環境 第2章

2025/02/22に公開
1

UNIXプログラミング環境 第2章

今回から3節ごとを目処に記事にします。
内容はToday I Learnedということで、学びを記す記事です。
 詳しいわけではないので悪しからず。
書籍はこちら
UNIXプログラミング環境

ファイルシステム

2.1 ファイルの基礎

  • ファイルとはバイトの集合。
  • ファイルはなんの制約も受けず、その内容に意味を持たされることはない
  • プログラムが解釈して初めて意味を持つ

これは周辺機器にも当てはまり、磁気テープからメール、パイプのような流れるデータもバイトの集合でしかない。

ファイルをいじるのが最も勉強になるのことで、プロンプトの操作に入る。

$ ed
a
now is the time
for all good people
.
w junk
36
q
$ ls -l
-rw-r--r-- 1 ~~~(省略)

od (octal dup : 8進数ダンプ)を使うと、バイトを全て目で見える形にできる。
-c オプションがバイトを文字と解釈せよという意味である。

$ od -c junk
0000000    n   o   w       i   s       t   h   e       t   i   m   e  \n
0000020    f   o   r       a   l   l       g   o   o   d       p   e   o
0000040    p   l   e  \n                                                
0000044

-b オプションで8進数を表示できる。

$ od -b junk
0000000   156 157 167 040 151 163 040 164 150 145 040 164 151 155 145 012
0000020   146 157 162 040 141 154 154 040 147 157 157 144 040 160 145 157
0000040   160 154 145 012                                                
0000044

空白のバイト数が040と知りました。
 ここで左端の7桁の数字は、そのファイルの中の位置、つまり、次に表示される文字が何番目に当たるかを8進数で示している。

8進数は昔のシステムの名残で、16進数の方が相性の良いシステムが増えていきている。

制御文字 (\nなど)も特殊に見えて、8進数で表示すればただの数値であるとわかる。

制御文字 対応する8進数の数値
改行 \n 012
タブ \t 011
バックスペース \b 010
キャリッジリターン \r 015

2.2 ファイルの種類

ファイルのフォーマットは、そのファイルを使うプログラムが決める。
 ファイル・システムが決めるわけではなく、プログラムがファイルの種類を決めるため、カーネルはファイルの種類を認知していない。
そこでfileコマンドが役にたつ。fileコマンドは拡張子を確認してfileの種類を決めるのではなく、先頭の数百バイトを読み、ファイルの種類を決める鍵となるものを探す。

実行可能形式のプログラムはわかりやすく、先頭にバイナリの"マジックナンバー"がついている。
16進数で表示する hexdumpを使用すると (max os を使用しています)

$ hexdump /bin/ed
0000000 feca beba 0000 0200 0001 0700 0000 0300
0000010 0000 0040 0100 2097 0000 0e00 0001 0c00
0000020 0080 0200 0200 0000 0100 2097 0000 0e00
0000030 0000 0000 0000 0000 0000 0000 0000 0000
....

先頭4bytesがマジックナンバーだそうなので、feca bebaがマジックナンバーだと推定できる。
 大きい数値になっていることが信憑性を担保していて、エディターでタイピングできない値がマジックナンバーとなる。 => ASCIIコードで入力できる値はマジックナンバーではないため、非常に大きな値が設定されているので断定できる。

他にも最初が #includeで始まっていればcファイルだと判断するし、.で始まっていれば nroffやtroffの入力ファイルと判断する。

テキストファイルのみで構成されることの利点などは書籍をご覧ください。かなり詳細に書かれていました。

2.3 ディレクトリとファイル名

全てのファイルには絶対パスとして /user/bin/(省略)といったファイルの名前を持っているが、lsコマンドを実行すると、junkのようなファイル名だけが出力される。
 lsはカレント・ディレクトリを持っていて、その中だけをlist upするためである。
 現在のカレント・ディレクトリは、 pwd (print working directory)で表示できる。

$ pwd
(がっつり本名が出たので省略)

ここでカレント・ディレクトリはプロセスにつけられた属性であり、ユーザやプログラムには属していない。
 もし親プロセスが子供のプロセスを生み出せば、子供プロセスは親のプロセスのカレント・ディレクトリを受け継ぐ。ただ子供のプロセスに何をしても、親プロセスに影響を与えない。
 これらの機能は当然、ファイルの組織化、階層化のためである。

$ mkdir recipes
$ cd recipes
$ pwd
(省略)
$ mkdir pie cookie
$ ed pie/apple
(省略)
$ ed cookie/choc.chip
(省略)

この例のように、pieのレシピが一箇所に集まった方が良いだろうということである。

du (disk usage)コマンドで、階層構造のうちどのファイルがどれくらいディスクを使用しているか閲覧できる。

$ cd recipes
$ du -a
8	./pie/apple
8	./pie
8	./cookie/choc.chip
8	./cookie
16	.

-aオプションはallを意味する。
 左の数字がファイルの保存に使用されているブロック数であり、1ブロックあたり、512バイトまたは 1024バイトである。


ファイルの探索Tips

$ du -a |grep (検索したいファイル名)
(結果)

ずっとお前を探していたんだ、、、


話は戻って、ディレクトリは通常のファイルと異なった性質を持つが、ファイルシステムの中ではファイルと同じような形で入っている。つまり、前述のodコマンドで指定するとバイトが見える。(驚き)

$ od -cb .

ウキウキして実行しましたが、Macではできませんでした。
Linuxで試したいです。

まとめ

今日はここまで!

  • ファイルとはバイトの集合
  • 種類を決めているのはプログラムで、本来ファイルは自由なもの
  • ディレクトリもファイルと大差はない、ファイルの位置を示すためのファイルというイメージ

今までなんとなくで済ましていた部分がUNIXを用いて基本的な構成を学ぶことで、全体が見えてきて、そのおかげで別の場所で浮かんでいた疑問が解決するシーンがありました。(具体例は浮かんでは消えてを繰り返したので割愛)

1章の記事に体系的に学ぶと書きましたが、今まで触ったことのあるコマンドばかりで新たな発見がなかった中、体系的に学ぶことの意義、効果が早速現れてモチベーションになりました。

2書の続きはこちら

Discussion

ko1nksmko1nksm

$ od -cb .

Linuxでも、おそらく現在のどの Unix でも見れないと思います。
UNIXプログラミング環境は原著が1983年の本なので、
40年前の内容であることに注意してください。
一部の内容は時代遅れになっています。