本文へジャンプ

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

送信されたすべての情報は安全です。

  • 閉じる [x]

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む


送信されたすべての情報は安全です。

  • 閉じる [x]

共通テーマ: アドバンスト・ファイルシステム・インプリメンター・ガイド: 第6回

initラッパーを使ってdevfsを導入する

Daniel Robbins (drobbins@gentoo.org), President/CEO, Gentoo Technologies, Inc.
Daniel Robbins氏は、ニューメキシコ州アルバカーキーに住んでいます。彼は、Gentooプロジェクトのチーフ・アーキテクト、Gentoo Technologies Inc. の社長/CEOです。著書に、Macmillanから出版されているCaldera OpenLinux Unleashed、SuSE Linux Unleashed、Samba Unleashed があります。Daniel氏は、小学2年のとき初めてLogoプログラム言語や、中毒になる恐れのあったPac Manに出会って以来、何らかの形でコンピューターに関係してきています。これで、彼がなぜSONY Electronic Publishing/Psygnosisでリード・グラフィック・アーチストを務めているかが分かるでしょう。愛妻Maryさんや、生まれたばかりの愛娘Hadassahちゃんとの時間をとても大切にしています。彼の連絡先はdrobbins@gentoo.org です。

概要: Linux 2.4のリリースとともに、ReiserFS、XFS、GFSを始めとするさまざまなファイルシステムが新たに登場しました。これらのファイルシステムは、厳密には何ができ、何に適しているのでしょうか。そして、Linuxの実稼働環境で安全に使用するにはどのようにすればよいのでしょうか。このアドバンスト・ファイルシステム・インプリメンター・ガイドでは、Daniel Robbins氏がこれらのアドバンスト・ファイルシステムをLinux 2.4環境にセットアップする方法を示し、これらの疑問に答えます。今回の記事では、(ついに!)initラッパーを使用してシステムを「devfsモード」に変換する方法について説明します。

日付:  2001年 10月 01日
レベル:  初級 この記事の原文:  英語
アクティビティー: 1331 ビュー
お気軽にご意見・ご感想をお寄せください: 


準備OK?

今回は、Linuxシステムのdevfs(Device Filesystem)への完全な変換を行います。devfsに関する連載記事を今回初めてお読みになる方は、まずこの連載記事の第4回をお読みください。第4回の記事は、devfsがどのようにしてデバイス登録に関する問題をカーネル・レベルで解決するかについて説明しています。その上で第5回をお読みください。Linuxシステムをdevfs対応とし、devfsへの最終的な変換ができる状態にするステップを説明しています。

以下に示す手順を実行する前に、必ず第5回の記事をお読みください。第5回で説明しているステップを省くと、これからインストールするinitラッパーは、正常に機能しなくなり、その結果システムがブートせず、緊急のリカバリーが必要となるでしょう。これでは、せっかく導入した意味がありません。第5回をすでにお読みの方は、先に進んでください。


initラッパー

始めに

第5回の記事の最後に、initラッパーの概念について紹介し、initラッパーがdevfsの初期設定に関するいくつかの問題を解決する方法として最適である理由を説明しました。ここからは、initラッパーの完全版について順を追って検討し、各部分の機能について考察します。それでは、見ていきましょう。

以下の例で、スクリプトの先頭に#!/bin/bashがあることから分かるように、initラッパーは実際にはbashスクリプトです。initラッパーを実行するにはbash 2.0以上が必要です。/bin/bash --versionと入力し、現在使用しているbashシェルが2.0以上であるかどうか確認します。2.0以上でなければ、/bin/bash2実行可能プログラムがインストールされているかどうか確認します。2.0以上であれば、スクリプトの先頭行を#!/bin/bash2に変更します。


initラッパーの先頭部分
                
#!/bin/bash
# Copyright 2001 Daniel Robbins <drobbins@gentoo.org>, Gentoo Technologies, Inc.
# Distributed under the GNU General Public License, version 2.0 or later.
trap ":" INT QUIT TSTP	
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
umask 022
if [ $$ -ne 1 ]
then
	exec /sbin/init.system $*
fi
            

それでは、このスクリプトをザッと見てみましょう。trapコマンドは、スクリプト実行中にスクリプトへのユーザーの(たとえば、ブート中のCtrl + C)割り込みを防ぎます。次に、適切なデフォルト・パスをexportし、デフォルトのumaskを022に設定します。デフォルトのumaskは、常にブート・プロセスの最初の方に設定した方がよいでしょう。それは、初期の2.4カーネル・リリースの多くに、デフォルトのumaskが0になるバグがあり、セキュリティー上の問題となるためです。

次に、最初の条件付きステートメントif [ $$ -ne 1 ]があります。$$は、bashによって現在実行中のプロセスのプロセスIDに置換されるため、実際には「このプロセスIDは1以外か」という質問をしていることが分かります。これはどんな意味を持つのでしょうか。このinitラッパーがブート・プロセス間にカーネルによって起動されている場合、PIDは必ず「1」となります。これは、PID「1」がinitプロセス用に予約済みのためです。PIDが1ではない場合、システム・ブート後にコマンド・ラインから実行されていると考えられます。/sbin/initコマンドには、ブート済みのシステムのrunlevelをスーパーユーザーが変更できるようにするという目的もあるため、これはよくあることです。この場合には、/sbin/init.systemにリネームされている元の/sbin/initexecするだけです。$*変数を使って任意のコマンド・ライン引数をinit.systemに渡すとinitラッパーは終了し、init.systemが実行を開始します。

カーネル・ブート・オプション

ただしブート時に、このラッパーをカーネルが開始している場合は、bashのPIDは1となり、この条件付きステートメント全体がスキップされ、bashはこのラッパーの実行を継続します。その続きは、以下の行です。


initラッパーの続き
                
mount -n /proc
devfs="yes"
for copt in `cat /proc/cmdline`
do
	if [ "${copt%=*}" = "wrapper" ]
	then
		parms=${copt##*=}
		#parse wrapper option
		if [ "${parms/nodevfs//}" != "${parms}" ]
		then
			devfs="no"
		fi
	fi
done
            

コードのこの部分までくると、このラッパーはブート・プロセス間にカーネルが実行していることになります。その次にまず行う操作は、ルート・ファイルシステムに対する/procのマウントですが、この時点ではまだ読み取り専用です。その後、便利なLinux機能を利用した、大きく複雑なbashコード部分を実行します。/proc/cmdlineの内容を見ると、どのようなオプションがLILOまたはGRUBによってカーネルに渡されたのか確認できます。私の開発用ボックスでは、/proc/cmdlineの内容は以下のとおりでした。


/proc/cmdlineの内容
                
# cat /proc/cmdline
root=/dev/hda6 hda=89355,16,63 mem=524224K
            

上記コードでは、/proc/cmdlineを使い、このwrapperというスクリプトで作成したカーネル・ブート変数を検索しています。カーネル・ブート・オプション内にwrapper=nodevfsがある場合、スクリプトはdevfsが有効になっていないと判断しますが、この変数が/proc/cmdline内にない場合には、このラッパーはdevfsの初期設定を開始します。これから分かることは、wrapper=nodevfsカーネル・ブート・オプションを使ってブートすることにより、devfsを簡単に無効化できるということです。その場合、devfs変数は「no」に設定され、それ以外の場合は「yes」に設定されます。

ラップの完了

ラッパーの残りの部分は以下のとおりです。


initラッパーの残りの部分
                
if [ "$devfs" = "yes" ]
then
 if [ -e /dev/.devfsd ] then
	clear
	echo
	echo "The init wrapper has detected that /dev has been automatically mounted by"
	echo "the kernel. This will prevent devfs from automatically saving and"
	echo "restoring device permissions. While not optimal, your system will still"
	echo "be able to boot, but any perm/ownership changes or creation of new compat."
	echo "device nodes will not be persistent across reboots until you fix this"
	echo "problem."
	echo
	echo "Fortunately, the fix for this problem is quite simple; all you need to"
	echo "do is pass the \"devfs=nomount\" boot option to the kernel (via GRUB"
	echo "or LILO) the next time you boot.  Then /dev will not be auto-mounted."
	echo "The next time you compile your kernel, be sure that you do not"
	echo "enable the \"Automatically mount filesystem at boot\" devfs kernel"
	echo "configuration option.  Then the \"devfs=nomount\" hack will no longer be"
	echo "needed."
	echo "read -t 15 -p "(hit Enter to continue or wait 15 seconds...)" else	
	mount -n /dev /dev-state -o bind
	mount -n -t devfs none /dev
	if [ -d /dev-state/compat ]
	then
			echo Copying devices from /dev-state/compat to /dev
			cp -ax /dev-state/compat/* /dev
	fi
 fi
 /sbin/devfsd /dev >/dev/null 2>&1;
fi 
exec /sbin/init.system $*

これで、devfsが「yes」に設定されている場合にのみ実行される、大きな条件付きステートメントまで来ました。そうでない場合には、devfs初期設定は完全にスキップされ、devfsのマウントも行われません。その場合、devfsではない通常のブートが実行されます。

ここではdevfsの設定を行っているわけですから、この条件付きステートメントの内容を検討しましょう。devfsがカーネルによってすでにマウントされているかどうか確認します。それには、/dev/.devfsdキャラクター型デバイスの有無を確認します。devfsがマウントされると、カーネルはこのデバイスを自動的に作成し、それ以降のdevfsdプロセスはそれを使ってカーネルと通信します。devfsがマウント済みの場合(ユーザーが「Automatically mount devfs at boot」カーネル・オプションを選択したために)、devfsの永続性機能をセットアップできないというメッセージが出力されます。これは、その操作を実行できるのは、devfsがカーネルによってマウントされていない場合のみであるためです。

デバイスの永続性

特に問題がなければ、前回最後に説明したdevfsのセットアップを実行し、/devを/dev-stateにバインド・マウントし、devfsファイルシステムを/devにマウントします。次いで、前回説明しなかったステップを実行します。/dev-state/compatディレクトリーの有無を確認し、それが存在する場合はその内容を/devに再帰的にコピーします。この手順は、一見するとやや冗長に見えるかもしれませんが(devfsdのデバイス永続性機能を利用しようとしているため)、必要かつ有効であることが分かります。compatディレクトリーが必要なのは、devfs対応のドライバーがないとdevfsdの永続性機能が機能しないためです。

したがって、devfs以外のカーネル・モジュールを使用する場合、手動で/devにデバイス・ノードを作成する必要があります。この方法の問題点は、この新しいデバイス・ノードがdevfsdに無視され、次回リブート時には消えてしまうことです。この問題の解決策となるのが/dev-state/compatディレクトリーです。devfs以外のモジュールの場合、/dev-state/compat内に従来のデバイス・ノードを作成するだけで、この便利なinitラッパーのステップによって、ブート時におけるdevfsファイルシステムへの手動による追加が可能です。

最後に、devfsdを起動してから条件付きステートメントを終了し、実際のinit、/sbin/init.systemexecして標準のシステム・ブート・プロセスを開始します。devfs対応システムになったことを除けば、すべて従来と変わりありません。


initラッパーのインストール

次に、initラッパーのインストール方法について説明します。まず、wrapper.shのソースを入手し、システム内(のどこか)に保存します。そして、以下のコマンドを実行します。


initラッパーのインストール
                
# cd /sbin
# cp init init.system
# cp /path/to/wrapper.sh init
# chmod +x init
            

これでinitラッパーがインストールされました。

umountの微調整

initラッパーを使用することで、initscriptの複雑な微調整の大部分を回避することができますが、どうしてもそれが必要な場合が一つあります。devfsファイルシステムが/devにマウントされたことから、おそらく、rcスクリプトによるルート・ファイルシステムのアンマウントが簡単にはできなくなります。幸い、この修正は簡単にできます。使用しているディストリビューションのrcスクリプトのインストール先に応じてcd /etc/rc.d; grep -r umount *またはcd /etc/init.d; grep -r umount *と入力し、rcスクリプト・ディレクトリーをgrepし、umountの出現箇所をすべて検索します。その後、umountを参照しているすべてのスクリプトで、umount-rオプション付きで呼び出されるようにします。特に重要なのは、ルート・ファイルシステムをアンマウントしている特定のumountコマンドですが、どれもこれもをumount -rとするのでもうまくいくはずです。

-rオプションを指定すると、umountはアンマウントが失敗した場合に読み取り専用としてファイルシステムの再マウントを試みます。ルート・ファイルシステムを整合状態とし、リブートできる状態にするにはこれで十分です。開いているデバイス・ノードが存在し、アンマウントできないものが/devにマウントされ、ルート・ファイルシステムのアンマウントができない場合でも問題はありません。

これで、ほぼリブートできる状態になりましたが、リブートの前にdevfsdについて考察し、互換デバイスとデバイス永続性が有効になるように/etc/devfsd.confを仕上げましょう。ご心配なく。devfsへの移行が完了するまで、あと1歩です。


devfsd.conf

使用しているエディターに/etc/devfsd.confをロードしてください。以下は、私がお勧めするdevfsd.confの最初の4行です。


devfsd.confの先頭部分
                
REGISTER        .*              MKOLDCOMPAT
UNREGISTER      .*              RMOLDCOMPAT
REGISTER        .*              MKNEWCOMPAT
UNREGISTER      .*              RMNEWCOMPAT
            

上記4行はそれぞれ、イベント(REGISTERまたはUNREGISTER)、正規表現(.*)、およびアクション(*COMPATストリング)からなります。これらにはどんな意味があるのでしょうか。最初の行は、任意のデバイス(.*は任意のデバイスと一致する正規表現)がカーネルに登録されている場合、MKOLDCOMPATアクションを実行するようにdevfsdに指示します。MKOLDCOMPATアクションは、devfsdに組み込まれているもので、「そのデバイスに対応する従来の互換デバイスをdevfsによって登録する」ものです。すでにお気づきと思いますが、デバイスの登録解除時に実行されるRM*COMPATアクションは、これらの特殊互換デバイスを適切に消去するためのものです。全体的に見ると、この4行は、デバイス登録時に互換デバイス(もしあれば)を作成し、デバイス登録解除時にその互換デバイスを削除するようにdevfsdに指示します。この行によって、IDEデバイス・ドライバーが/dev/ide/host0/bus0/target0/lun0/discdevfsスタイル・デバイスをシステムに登録すると、devfsは一致する/dev/hda互換スタイル・デバイスを自動的に作成します。これは、mountfsckなど、従来のデバイス名を含む/etc/fstabを読み込む可能性のあるコマンドにとって非常に役立ちます。多くの場合、互換デバイスの作成によってdevfsの移行はシームレスなものとなります。私がお勧めするdevfsd.confの次の行は以下のとおりです。

モジュールの自動ロード


devfsd.confの続き
                
LOOKUP          .*              MODLOAD
            

このエントリーは、任意のデバイス(.*)が「ルックアップ」されている場合は必ずMODLOADアクションを実行するようにdevfsdに指示します。プログラムが特定のデバイス・ノードの存在を探す場合に、このルックアップが行われます。MODLOADアクションにより、modprobe /dev/mydevが実行されます。/dev/mydevは、特定のプロセスが見付けようとしているデバイス名です。この機能(および適切に構成された/etc/modules.conf)によって、音楽プレイヤーなどの起動時に、オンデマンドでのサウンド・カード・ドライバーの自動ロードが可能となります。

デバイスの永続性

devfsd.confの次の数行は、以下のとおりです。


devfsd.confの続き
                
REGISTER        ^pt[sy]/.*      IGNORE
CHANGE          ^pt[sy]/.*      IGNORE
REGISTER        .*              COPY    /dev-state/$devname $devpath
CHANGE          .*              COPY    $devpath /dev-state/$devname
CREATE          .*              COPY    $devpath /dev-state/$devname
            

これらの行は、デバイス・アクセス権や所有権の変更のため、またユーザーが作成した新しい互換デバイスのためのリポジトリーとして/dev-stateを使用するようdevfsdに指示します。最初の2行は、疑似端末デバイスをカーネルに登録する場合、あるいはその属性を変更する場合に、いずれの特殊アクションも実行しないようdevfsdに対して明示的に指示します。これらの行がないと、リブートしても疑似端末のアクセス権や所有権が保持されることになります。ただし、システムの起動直後に疑似端末デバイスに対するデフォルトのアクセス権をそれぞれ設定する必要があるため、これは最適なものとは言えません。

次の3行で、他のすべてのデバイスに対して/dev-state永続性を有効にします。具体的には、デバイス登録時またはdevfsdの起動時(ならびに既存の互換デバイスに上書きする際)に/dev-stateからすべての属性を復元し、属性の変更ならびに互換デバイスの新規作成後、直ちに/dev-stateにバックアップします。

CFUNCTIONとsymlinks

私の推薦するdevfsd.confの末尾は、以下のようなものです。


devfsd.confの末尾
                
REGISTER        ^cdrom/cdrom0$          CFUNCTION GLOBAL symlink cdroms/cdrom0 cdrom
UNREGISTER      ^cdrom/cdrom0$          CFUNCTION GLOBAL unlink cdrom
REGISTER        ^misc/psaux$            CFUNCTION GLOBAL symlink misc/psaux mouse
UNREGISTER      ^misc/psaux$            CFUNCTION GLOBAL unlink mouse
            

この最後の4行はオプションですが、一考の価値があります。/dev-stateの永続性は、デバイス・ノードに対してはうまく働きますが、シンボリック・リンクに対してはまったく機能せず、シンボリック・リンクは無視されます。ここで1つの疑問が生じます。/dev/mouseまたは/dev/cdrom symlinkを存在させるだけでなく、リブートを行っても永続性を保持するようにするにはどうすればよいのでしょうか。幸い、devfsdはきわめて柔軟な構成が可能であり、これら4行(またはシステムに合わせてカスタマイズした行)によってそれを行うことができます。最初の2行は、/dev/cdrom/cdrom0デバイスの登録時に/dev/cdrom symlinkを示すようにdevfsdに指示します。そのために、devfsdは指定されたlibc関数(この場合はsymlink()unlink())の動的呼び出しを実際に実行します。最後の2行は、同じ方法を用いて、/dev/misc/psaux(PS/2マウス)デバイスをdevfsに登録する際に/dev/mouse symlinkを作成するものです。システムに合わせてこれらの行をカスタマイズし、このファイルを保存します。このdevfsd.confをダウンロードして使用することもできます。


リブート前の注意

リブートを行う前に、Richard Gooch氏のdevfs FAQに目を通しておくことをお勧めします。devfsの命名規則に関する情報があり、新しいスタイルのデバイス名に慣れた場合、特に役立ちます(以下の参考文献を参照)。また、ブート関連の問題修正のため「非常時のbashの救済」が必要となった場合に備えて、この連載記事(第5回)のコピーを印刷しておくこともお勧めします。何らかの理由でこの新しいinitラッパーがうまく機能しない場合、非常時の救済指示に従ってルート・ファイルシステムを読み取り/書き込み用として再マウントし、以下のステップを実行すれば、いつでも削除することができます。


必要に応じて、ラッパー適用前の状態に戻すためのステップ
                
# cd /sbin
# mv init wrapper.sh
# mv init.system init

上記ステップの実行後、ファイルシステムを読み取り専用として再マウントし、リブートすれば、システムはラッパーを適用する前の状態に戻ります。では、上記作業を行ってリブートし、devfsを楽しんでください。


参考文献

著者について

Daniel Robbins氏は、ニューメキシコ州アルバカーキーに住んでいます。彼は、Gentooプロジェクトのチーフ・アーキテクト、Gentoo Technologies Inc. の社長/CEOです。著書に、Macmillanから出版されているCaldera OpenLinux Unleashed、SuSE Linux Unleashed、Samba Unleashed があります。Daniel氏は、小学2年のとき初めてLogoプログラム言語や、中毒になる恐れのあったPac Manに出会って以来、何らかの形でコンピューターに関係してきています。これで、彼がなぜSONY Electronic Publishing/Psygnosisでリード・グラフィック・アーチストを務めているかが分かるでしょう。愛妻Maryさんや、生まれたばかりの愛娘Hadassahちゃんとの時間をとても大切にしています。彼の連絡先はdrobbins@gentoo.org です。

不正使用の報告のヘルプ

不正使用の報告

ありがとうございます。 このエントリーは、モデレーターの注目フラグが設定されました。


不正使用の報告のヘルプ

不正使用の報告

不正使用の報告の送信に失敗しました。


developerWorks: サイン・イン


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


お客様が developerWorks に初めてサインインすると、プロフィールが作成されます。 プロフィールで選択した情報は公開されますが、いつでもその情報を編集できます。 お客様の姓名(非表示設定にしていない限り)とディスプレイ・ネームは、投稿するコンテンツと一緒に表示されます。

表示名をお選びください

developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

(半角英数字で3文字以上31文字以下にする必要があります)


「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 利用条件

 


この記事を評価する

コメント

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source
ArticleID=228236
ArticleTitle=共通テーマ: アドバンスト・ファイルシステム・インプリメンター・ガイド: 第6回
publish-date=10012001
author1-email=drobbins@gentoo.org
author1-email-cc=

タグ

Help
このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。

スライダーバーを使用することで、より多く(少なく)タグを表示します。

人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。

マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。

このタグで、My developerWorks のすべてのタイプのコンテンツを見つけるために検索フィールドを使用します。人気のタグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するトップのタグを表示します。マイ・タグは、この特定のコンテンツ・ゾーン(例えば、Java テクノロジー、Linux や WebSphere など)に対するお客様ご自身のタグを表示します。