🐧 Linux 総合学習プラットフォーム
システムコール ・ 上級

man 2 でシステムコールを調べる

Linuxのマニュアルはセクション番号で分かれており、セクション2がシステムコール、セクション3がライブラリ関数です。同じ名前でも別物のことがあるため、man 2 open のように番号を指定して目的のページを開きます。各ページには概要(SYNOPSIS)、必要なヘッダファイル、引数の意味、戻り値、そして失敗時に errno へ設定されるエラー一覧(ERRORS)が載っています。どんな番号があるかは man man で確認でき、apropos でキーワード検索もできます。正確な仕様の一次情報として、まず man 2 を引く習慣が大切です。

システムコール(syscall)やライブラリ関数を正しく使うには、引数の意味や戻り値、そして失敗したときの挙動を正確に知る必要があります。その一次情報を提供してくれるのが、Linuxに標準で備わっているオンラインマニュアル、manです。ネット上の解説記事も便利ですが、情報が古かったり、対象のディストリビューションやバージョンによって違ったりすることがあります。いま自分が使っているこのシステムで、その関数が実際にどう振る舞うのか――その答えを最も確実に教えてくれるのが、手元のmanです。低レイヤを扱うなら、困ったらまずmanを引く習慣を身につけることが、遠回りに見えて実は最短の近道になります。仕様を推測で済ませないことが、信頼できるプログラムを書く第一歩です。

なぜセクション番号が必要なのか

manを使ううえで最初に理解すべきは「セクション」という区分です。Linuxのマニュアルは内容ごとに番号で分類されており、よく使うものを挙げると、セクション1が一般のコマンド、セクション2がシステムコール、セクション3がライブラリ関数(libcなどが提供する関数)、セクション5がファイルフォーマットや設定ファイルの書式です。なぜこの区別がそれほど重要なのか。それは、同じ名前でも内容の異なるページが複数存在しうるからです。代表例がwriteです。セクション2のwriteはカーネルが直接提供するシステムコール、それとは別にライブラリ側の説明があり、両者は属する層が違います。printfに至っては、コマンドとしてのprintf(セクション1)と、ライブラリ関数としてのprintf(セクション3)が別々に存在します。番号を指定せずにman writeと打つと、一番若いセクションのページが優先して表示されるため、自分が見たかったものと違うページが出てしまうことがあるのです。この食い違いを避けるために、セクション番号の存在を意識することが大切になります。

man 2 でシステムコールを引く

目的のシステムコールを確実に開くには、セクション番号を明示してman 2 openやman 2 readのように引きます。開いたページには、どの関数でも決まった構成で情報が並んでいます。NAME(名前と一行の説明)、SYNOPSIS(必要なヘッダファイルと、関数の正確な宣言)、DESCRIPTION(動作の詳しい説明)、RETURN VALUE(戻り値が何を意味するか)、そしてERRORS(失敗したときにerrno(errno)へ設定されうるエラーの一覧)です。この構成が頭に入っていると、長いページでも知りたい部分へ直行できます。たとえばman 2 openを引けば、冒頭のSYNOPSISに #include <fcntl.h> というインクルードすべきヘッダと、int open(const char *pathname, int flags, ...); という関数の形が示されます。SYNOPSISは、コードを書くときにどのヘッダを取り込み、引数をどの順で渡せばよいかを確認する第一の手がかりです。続いて、フラグにO_RDONLYやO_CREATが使えること、成功するとファイルディスクリプタ(fd)を返し、失敗すると-1を返すこと、そしてERRORSの節に、ENOENTやEACCESがそれぞれどんなときに設定されるかが、根拠とともに列挙されています。straceで見つけた失敗の意味を裏取りしたいとき、このERRORSの節が決定的な手がかりになります。なお、システムコールの中には、man 2のページの末尾に「実際にはglibcのラッパー関数を経由して呼ばれる」といった注記が書かれているものもあり、ライブラリとシステムコールの関係を理解する助けにもなります。

マニュアル内の歩き方

manのページはlessというページャ(画面送りツール)で表示されるため、その操作を覚えておくと閲覧が格段に快適になります。スペースキーで一画面進み、bキーで一画面戻り、スラッシュに続けて語を打てばページ内を前方検索でき、nキーで次の一致へ移動します。gで先頭、Gで末尾へ一気に飛び、qで終了します。マニュアルは長いものが多いので、たとえばERRORSの節だけを読みたいときは /ERRORS と検索すれば一足飛びにそこへ到達できます。この検索を覚えるだけで、目当ての情報にたどり着く速さがまるで変わります。同じ操作感は、前章で見たstraceの出力をlessに流して読むときにもそのまま通用します。どんなセクションが存在するのか、manそのものの使い方を知りたいときは、man manを引けば一覧と説明が読めます。英語のページが基本ですが、SYNOPSISやERRORSといった項目の構成は世界共通なので、まずは見出しの場所を覚えて拾い読みするところから慣れていくとよいでしょう。

名前がうろ覚えのとき ― apropos と関連情報

「ファイルの権限を変える関数があったはずだが、肝心の名前が思い出せない」――そんなときに使うのがaproposです。aproposはキーワードでマニュアルの見出しを横断検索し、関連しそうなページの一覧を返してくれます。たとえばapropos directoryと打てば、ディレクトリに関係する関数やコマンドが、それぞれのセクション番号付きでずらりと並びます。その中から目当てのものに当たりを付け、改めてman 2やman 3で詳細を読む、という流れで使います。なお、各manページの末尾にはSEE ALSOという節があり、関連するほかのページが示されています。そこではopen(2)やclose(2)のように、関数名のうしろにセクション番号が括弧付きで記されています。この表記を見れば、その関数を調べるには何番のセクションを引けばよいかが一目で分かります。正確な仕様は推測で済ませず、システムコールならman 2、ライブラリ関数ならman 3で必ず一次情報を確かめる――この地道な姿勢が、信頼できる低レイヤプログラムを書くための確かな基礎になります。

この項目に出てくる用語

システムコールしすてむこーる
アプリがカーネルに処理を依頼する公式の窓口。
errnoえらーなんばー
直近のシステムコール失敗の原因を表す番号。

関連コマンド

man 2 openman 3 printfapropos

▶ 学習アプリでこの続きを学ぶ・演習する