前回は,プログラムのソース・ファイルの中を見てライブラリ関数の役割を学びました。ライブラリ関数はカーネルの処理ではありません。今回は,いよいよカーネルの内部で処理するシステム・コールについて説明します。システム・コールの役割や,システム・コール関数の探し方,ライブラリ関数との違いを学びましょう。

 前回は,カーネルを読みこなすために必要となるC言語について最小限の知識と,ユーザーが作成したC言語のプログラム中に含まれるライブラリ関数について解説しました。ソース・プログラムをコンパイルする際に自動的にライブラリ関数を参照して連結(リンク)するので,気づかないうちにライブラリ関数を使っています。しかし,データベースや暗号化などのライブラリを利用するときは,ライブラリのディレクトリ位置(-Lで指定)やライブラリ・ファイル名(-lで指定)を明示しなければ,リンク・エラーとなる場合があります。

 また,前回は,ライブラリ関数内から「システム・コール」というカーネルの関数を呼んでいることを簡単に解説しました。今回はその続きで,カーネル・ソース内のシステム・コールを確認します。初めてカーネルを読む人でも具体的にシステム・コールを理解できるように,ログインしているユーザー名を表示させる「whoami」コマンドを例に取り上げました。

whoamiをマニュアルで調べる

 最初に「man whoami」を実行してマニュアルでwhoamiコマンドを確認すると,「(1)」と表示されますので,ユーザー・コマンドであることが分かります。「info whoami」で詳細が表示されます。

 ユーザーがキーボードからwhoamiコマンドを入力すると,シェル(bash)は/usr/binディレクトリにあるwhoamiファイルを発見して実行し,実行結果を画面に表示します。


$ whoami

akamatsu

 今回はシェルのソースを見ることが目的ではないので説明は省きますが,bashのソース・プログラムを確認すると,「execute_disk_command()」という関数を使って実行可能ファイルを起動しているのが分かります。

 次に,whoamiのソースを見てみます。rpmコマンドを実行して,whoamiファイルをインストールしたパッケージを確認すると,「coreutils」であると分かります(図1)。


# rpm -qif /usr/bin/whoami

Name : coreutils Relocations: (not relocatable)
Version : 5.2.1 Vendor: Red Hat, Inc.
Release : 7 Build Date: Wed 05 May 2004 01:24:12 AM JST
図1●rpmコマンドを使ってwhoamiのパッケージを調べる
「coreutils」だと分かる。

whoamiコマンドのソース・プログラム

 coreutils-5.91.tar.bz2を取得してtarコマンドで解凍・展開します。作成されたcoreutils-5.91/srcディレクトリにwhoami.cをはじめ,数多くのソース・プログラムがあります(図2)。


# tar jxvf coreutils-5.91.tar.bz2

# ls -l coreutils-5.91/src/*.c|grep whoami

-rw-r--r-- 1 root root 2679 Mar 24 20:43 coreutils-5.91/src/whoami.c
図2●coreutilsパッケージを展開する

 whoami.c(図3)は100行程度のプログラムで,重要部分は88行目の「geteuid()」および,89行目の「getpwuid()」という関数です。


63 int
64 main (int argc, char **argv)
65 {
66 struct passwd *pw;
67 uid _ t uid;
   途中省略
88 uid = geteuid ();
89 pw = getpwuid (uid);
90 if (pw)
91 {
92 puts (pw->pw _ name);
93 exit (EXIT _ SUCCESS);
94 }
95 fprintf (stderr, _ ("%s: cannot find name for user ID %lu\n"),
96 program _ name, (unsigned long int) uid);
97 exit (EXIT _ FAILURE);
98 }
図3●プログラム1(whoami.c)の内容

 最初に88行目のgeteuid()関数をマニュアルで確認しましょう。


# man geteuid

 表示結果の“見所”は次の3点です。

・マニュアル番号が「(2)」なので,システム・コールである。

・ ヘッダー・ファイルは「unistd.h」と「sys/types.h」の2つである。

・ geteuid()関数は引数が不要で,uid_t型の値が戻る(uid_tは別に定義された型名です)。