/ «2008-03-16 (Sun) ^ 2009-01-01 (Thu)» ?
   西田 亙の本:GNU 開発ツール -- hello.c から a.out が誕生するまで --

Categories Books | Hard | Hardware | Linux | MCU | Misc | Publish | Radio | Repository | Thoughts | Time | UNIX | Writing | プロフィール


2008-03-23 (Sun)

[Thoughts] プログラマの教養は manual pages に宿る (その8)

インクルード処理の意味を掴んだところで、各環境における manual pages の実際を見てみましょう。manual pages は内容に応じて「セクション」に分類されていますが、その分類方法や記述内容には、環境ごとに違いがあります。

Linux man-pages online

まず最初に Linux を見てみましょう。Linux では永らく系統立った manual pages の管理・公開は行われていませんでしたが、ようやく www.kernel.org 上でも Linux man-pages online という形で、オンラインマニュアルが提供されるようになりました。

この背景には、Michael Kerrisk 氏による Linux man-pages project の存在があります。Kerrisk 氏のブログ LINUX MAN-PAGES では、細かなアップデートの状況が公開されていますので、Linux 野郎は要フォローです。

それでは、Linux man-pages online の全体像を示します。manual pages の各セクションには、概略を記述した intro (INTROduction) と呼ばれるページが用意されているため、セクションごとにそのタイトルとリンクをまとめてみました。

セクション1 User commands and toolsUNIX 環境に関する概略説明
セクション2 Linux system callssyscalls.2, errno.3 へ言及
セクション3Library functions excluding the system call wrapperslibc, libm, librt に関する簡単な説明
セクション4Special device filesテンプレートのみ
セクション5File formatsテンプレートのみ
セクション6Gamesテンプレートのみ
セクション7Miscellaneous thingsテンプレートのみ
セクション8Administration and privileged commandsテンプレートのみ

UNIX の慣習にもとづき、合計8セクションから構成されていますが、実際に中身が用意されているのはセクション1, 2, 3のみです。順番に見ていきましょう。

セクション1の実体は intro.1 であり、Introduction to user commands と名付けられています。*BSD の intro.1 はほぼテンプレートファイルのままですが、Linux の場合は、ログイン・シェル・パス名・ディレクトリ・ファイルシステムについて、簡単に解説されています。

man 2 syscalls

セクション2はシステムコールを担当していますが、Linux の intro.2 は秀逸です。DESCRIPTION の先頭には次の一節が据えられています。

DESCRIPTION

Section 2 of the manual describes the Linux system calls.  A system call is an
entry point into the Linux kernel.  Usually, system calls are not invoked
directly: instead, most system calls have corresponding C library wrapper
functions which perform the steps required (e.g., trapping to kernel mode) in
order to invoke the system call.  Thus, making a system call looks the same as
invoking a normal library function.

For a list of the Linux system calls, see syscalls(2).

「通常、システムコールは直接呼び出されるのではなく、Cライブラリのラッパー関数を介して実行される」と明記してあります。ちなみに、このような表記は *BSD にはありません。

続いて、「システムコール一覧については syscalls.2 を参照せよ」とあります。syscalls(2) でも、"System calls and library wrapper functions" と題して、システムコールとラッパー関数の関係が解説された後に、System call list が掲載されています。System call list は、ハイパーリンク付きのシステムコール名に、当該システムコールが採用もしくは削除されたカーネルバージョン番号が併記された、大変重要な資料です(下記に先頭部分を抜粋)。

 System call                 Kernel        Notes
 -----------------------------------------------------------------------
 _llseek(2)
 _newselect(2)
 _sysctl(2)
 accept(2)
 access(2)
 acct(2)
 add_key(2)                  2.6.11
 adjtimex(2)
 afs_syscall(2)
 alarm(2)
 alloc_hugepages(2)          2.5.36        Removed in 2.5.44
 bdflush(2)
 bind(2)
 break(2)
 brk(2)
 cacheflush(2)                             Not on i386
 capget(2)                   2.2
 capset(2)                   2.2
 chdir(2)
 chmod(2)
 chown(2)
 chown32(2)                  2.4
 chroot(2)
 clock_getres(2)             2.6

man 2 _syscall

さて、ここまで読み進めてきて「ラッパー関数の世話にならずに済む方法はないものか?」とお悩みの方もいらっしゃることでしょう。そんな方のために、intro.2 の NOTES 中に ”Calling Directly” が用意されています。

CALLING DIRECTLY

In most cases, it is unnecessary to invoke a system call directly, but there are
times when the Standard C library does not implement a nice wrapper function for
you.  In this case, the programmer must manually invoke the system call using
syscall(2).  Historically, this was also possible using one of the _syscall
macros described in _syscall(2).

_syscall(2) には、Cソースファイル中からシステムコールを直接呼び出すための方法が書かれています(カーネル 2.4 およびカーネル 2.6.19 まで対応、カーネル 2.6.20 以降のヘッダーファイルは非対応のため注意)。実例として、sysinfo(2) システムコールを直接呼び出すプログラムが掲載されていますので、参考になるでしょう。

man 3 errno

システムコールの次はエラー番号ですが、intro.2 では "RETURN VALUE" として次のように記述されています。

RETURN VALUE

On error, most system calls return a negative error number (i.e., the negated
value of one of the constants described in errno(3)).  The C library wrapper
hides this detail from the caller: when a system call returns a negative value,
the wrapper copies the absolute value into the errno variable, and returns -1 as
the return value of the wrapper.

「ラッパー関数は、システムコールがエラー発生時に返す負の数を絶対値に変換した上で errno に格納し、リターン時には -1 を返す」とあり、エラー番号一覧は errno(3) に記載されていることが分かります。システムコールのエラー値であることを考慮すれば、errno の manual page は本来セクション2に属するはずですが、上に述べた理由から Linux では Cライブラリと同じセクション3に配置されているのです。

なお、errno(3) に記載されている最後の NOTES は必見です。errno を処理する際に、初心者のほとんどがハマる「落とし穴」について記載されています(その昔、私もハマりました)。

Library functions excluding the system call wrappers

最後のセクション3ですが、まず "Library functions excluding the system call wrappers" というタイトルが目を引きます。「システムコールに対するラッパー関数を除くライブラリ関数群」と明記されており、システムコールの実体はCライブラリ中のラッパー関数であることを示唆しています。なかなか渋い表現だと思いますが(このような表記は *BSD にはない)、内容は libc, libm, librt について簡単に触れるだけで、中身はほとんどありません。

全体の印象として、Linux ではセクション2に力が入れられており、中でもシステムコールとCライブラリ・ラッパー関数への言及は注目に値します。カーネルバージョンに対応したシステムコール一覧表も、不完全ではあるものの評価できる点でしょう。しかしながら、セクション3の内容は壊滅的。このあたりは、カーネル開発を主体に据える Linux の宿命と言えるかもしれません。

最後に、Linux man-pages online のユーザーインターフェイスですが、大変質素な出で立ちであり、検索も Google 経由になっています。

Debian hypertext manual pages

次に、Linux ディストリビュータの中では、最も資源管理が徹底している Debian を見てみましょう。Debian が提供する manual pages は、Debian hypertext manual pages で公開されています。

Linux man-pages project とは大きくことなる点として、

  • Collection
  • Output format
  • Languate

の3点があります。Collection は、Debian のバージョンごとに保管された manual pages であり、現時点で Debian sid, Debian 3.1 sarge, Debian 4.0 etch の3種類が用意されています(sid がデフォルト)。

Output format は、その名の通り出力形式であり、HTML, ポストスクリプト, PDF, ASCII コードセット, Latin 1 コードセットの計5種類による出力が可能です。

Language は記述言語の選択であり、14種類の言語から選択可能(デフォルトは英語)。

続いてその内容ですが、先ほどの Linux man-pages project が配布しているファイルと同じものです。

セクション1User commands and toolsUNIX 環境に関する概略説明
セクション2Linux system callssyscalls.2, errno.3 へ言及
セクション3Library functions excluding the system call wrapperslibc, libm, librt に関する簡単な説明
セクション4Special device filesテンプレートのみ
セクション5File formatsテンプレートのみ
セクション6Gamesテンプレートのみ
セクション7Miscellaneous thingsテンプレートのみ
セクション8Administration and privileged commandsテンプレートのみ
セクション9System kernel interfacesコーディングスタイルに関する簡単な説明

ただし、セクション9は Linux man-pages online には見られない、Debian 特有のセクションになっています。"System kernel interfaces" と題するその内容は、コーディング規約などについて簡単に触れているだけであり、最後の HISTORY には次のような記述があります。

    The intro section manual page appeared in FreeBSD 2.2.

なぜ、このページだけ FreeBSD 由来なのでしょうか?

FreeBSD hypertext manual pages

FreeBSD は NetBSD, OpenBSD とはことなり、x86 アーキテクチャに特化した BSD ですが、その manual pages は他環境とは一風変わっています。

FreeBSD hypertext manual pages には、UNIX Seventh Edition を筆頭にして、2.10 BSD, SunOS, HP-UX, 386BSD, Darwin, Minix 2.0, NetBSD, OpenBSD, Linux Slackware, Red Hat Linux, SuSE Linux, Plan 9 など合計183種類にも及ぶOSのマニュアル環境が揃えられています。

セクション1General commandsほぼテンプレートのみ
セクション2System calls and error numbersシステムコールエラー一覧およびカーネル関連用語の概説
セクション3C library functions9種類のライブラリ一覧
セクション4Special files and hardware supportデバイスの概説
セクション5File formastsテンプレートのみ
セクション6Games and demosなし
セクション7Miscellaneous information pagesテンプレートのみ
セクション8System maintenance commandsシステム管理コマンドのごく少数に触れる程度
セクション9Kernel internalsコーディングスタイルに関する簡単な説明

セクション構造やユーザインターフェイスも Debian とほぼ同様であり、Debian hypertext manual pages は、FreeBSD の成果を踏襲していたことが分かります。

セクション1は Linux とはことなり、テンプレートのみ。セクション2には、システムコールのエラーコードとカーネルに関連する基礎用語の解説が示されていますが、Linux のようなシステムコール一覧は示されていません。セクション3では、9種類のライブラリに関して簡単に説明されています。セクション4ではデバイスに関する概略が述べられており、セクション8では10種類の管理コマンドが羅列されているのみです。セクション9は、Debian と同様。

セクション3に Linux にはない姿勢が若干見受けられるものの、全体的には「すべての記述が中途半端」という印象を受けます。

OpenBSD manual pages

次は、セキュリティと安定性を至上命題に掲げる OpenBSD を見てみましょう。OpenBSD は FreeBSD とはことなり、i386 PC をはじめとして, PowerPC Mac, Alpha, SPARC, Zaurus, LANDISK など合計24アーキテクチャをサポートしています。

セクション1General commandsテンプレートのみ
セクション2System calls and error numbersシステムコールエラー一覧およびカーネル関連用語の概説
セクション3C library functions57種類のライブラリ一覧およびライブラリ構造の概説
セクション4Special files and hardware supportなし
セクション5File formastsテンプレートのみ
セクション6Games and demos45種類のゲーム一覧
セクション7Miscellaneous information pages26種類の解説ページ一覧
セクション8System maintenance commandsシステム管理コマンドについてグループ別に概説
セクション9Kernel internalsテンプレートのみ

OpenBSD の manual pages で際だっている点は、セクション3において、57種類におよぶシステムライブラリ群が列挙されていること。セクション7では、ASCII キャラクタセット, DES アルゴリズムモード, 環境変数 など26種類の解説ページが紹介されていること。セクション8では、fsck, mount など基本管理コマンドの紹介の他に、機能別に各種デーモンがまとめられていること。また、これはご愛敬ですが、今回紹介する環境の中では唯一、セクション6に属するゲームなどが紹介されている点が挙げられます。

最後に、OpenBSD manual pages のトップページには "Very Important For New Systems" と題して afterboot(8) という名前の manul page が紹介されています(FreeBSD に同ページは存在しない)。これは、インストール完了後に管理者がチェックすべきポイントを解説したものですが、簡潔で良くまとまっており、*BSD のみならず Linux 環境でも役立ちます。

もっとも、最近の Linux インストーラはバカチョン式になっており、このようなページは事実上不要になっているのかもしれませんが・・。

NetBSD manual pages

最後に、NetBSD 環境です。移植性に重点を置いている NetBSD は、現時点で56種類ものアーキテクチャに対応しています。

セクション1General Commandsテンプレートのみ
セクション2System Calls And Error Numbersシステムコールエラー一覧およびカーネル関連用語の概説
セクション3C Library Functions49種類のライブラリ一覧
セクション4Special Files And Hardware Supportデバイス概説および主要デバイス名一覧
セクション5File Formatsテンプレートのみ
セクション6Games And Demosテンプレートのみ
セクション7Miscellaneous Information Pages13種類の解説ページ一覧
セクション8System Maintenance Commandsシステム管理コマンドのごく少数に触れる程度
セクション9Kernel Internalsカーネル内部の処理関数を機能別(全16分野)に解説

NetBSD manual pages の特徴ですが、セクション3で紹介されている49種類のライブラリのうち、Cライブラリの表記にご注目。

 libc (-lc)  The standard C library.  When using the C compiler cc(1), it
             is not necessary to supply the linker flag -lc for these
             functions.  There are several subsystems included inside
             libc:
 
             standard I/O routines
                     see stdio(3)
 
             database routines
                     see db(3)
 
             bit operators
                     see bitstring(3)
 
             string operators
                     see string(3)
 
             character tests and character operators
 
             encryption and hash routines
                     see md4(3) and md5(3).
 
             storage allocation
                     see mpool(3) and malloc(3)
 
             time functions
                     see time(3)
 
             signal handling
                     see signal(3)

stdio, string, time, signal, メモリ割り当てなど、機能ごとに分類された10ページの解説へのポインタが示されています(この記述は NetBSD のみ)。実は、stdio(3) や signal(3)などのページ自身は、OpenBSD, FreeBSD にも用意されているのですが、両者は intro(3)においてその存在に触れていません。ちょっとした事ではあるのですが、ユーザのとまどいを先読みして適切に対処する NetBSD の配慮はさすがです。

続くセクション4では、デバイスの取り扱いに関する概略と主要デバイスの一覧が示されており、セクション9には今回紹介した環境の中で唯一、カーネルの内部構造に関する詳細な解説が納められています。取り扱っている内容は、メモリ管理, プロセス制御, ファイルシステム, ネットワークなど16分野にも及び、これから NetBSD カーネルを学ぼうとする人にとっては、最良の knowledge navigator となることでしょう。

ちなみに、NetBSD にも afterboot(8) は用意されており、その最後にはカーネルのビルド・インストール方法とシステムのテスト方法が記されています。

SYSTEM TESTING

At this point, the system should be fully configured to your liking.  It
is now a good time to ensure that the system behaves according to its
specifications and that it is stable on your hardware.  You can easily do
so by running the test suites available at /usr/tests/, assuming that you
installed the tests.tgz set.  If not, you can install it now by running:

       # cd /
       # tar xzpf /path/to/tests.tgz

Once done, edit the /etc/atf/NetBSD.conf file to tune the configuration
of the test suite, go to /usr/tests/ hierarchy and use the atf-run(1) and
atf-report(1) utilities to run all the tests in an automated way:

       # cd /usr/tests/
       # atf-run | atf-report

"SYSTEM TESTING" という機能は見慣れないものですが、これは 2007年に実施された Google Summer of Code の成果を取り入れたもので、ATF (Automated Testing Framework) と名付けられています。

このように NetBSD の manual pages 中では、カーネルの構造解説に力が入れられると共に、ATF のような真新しい機能に関しても、ユーザに混乱が生じることがないように、文書化が徹底されている点が印象的です。

それぞれの環境、それぞれの manual pages

ここまで、5つの環境の manual pages を見比べてきましたが、開発者の考えや姿勢に応じて、その内容には大きな違いがあることがお分かり頂けたかと思います。

当初の予定では今回が最終回になる予定だったのですが、「A君の素朴な疑問」には次回答えたいと思います。

続く