Getting Started With Kernel Hacking

「私はユーザスペースのスレッドとデバイスドライバの実装には、問題があるのではないかと疑問を持っている。」Linuxカーネルの開発を議論しているLinux Kernel Mailing List(LKML)では、時にこんな突拍子もないメールが来ることがある。

今回は、Linux Kernel Mailing List(LKML)での先輩方の、カーネル開発初心者への素早い対応ぶりと、カーネル開発入門に関する議論を紹介する。

4月27日10時6分にS.Kartikeyanは、このような内容のメールをLKMLに投稿した。

Doubt Regarding Multithreading and Device Driver

私のところには/dev/sknというデバイスドライバがある。それは基本的なドライバの操作であるskn_open、skn_release、skn_ioctlを実装しているものだ。
私は struct file *filp->private_dataへあるものを格納しているのだが、これがプロセス間でうまく共有できないために、その中の何かをアクセスするか置く間、ロックさせることができない。
filp->private_dataにアクセスするsmpカーネルでのioctl呼出しで、マルチスレッドのプログラムが競合するような状態があるのだろうか。

Max Kellermannが答えた。

君はカーネル変数について話しているようだね。カーネルメモリはすべてのプロセス中で共有される。つまり*ロックする*必要がある。

これに対してS.Kartikeyanがさらに聞いた。

しかし私は、(デバイスドライバ関数に渡される)プロセスのプライベート変数であるfile->private_dataの中のものを共有しようとしているのだが、それでも?

今後はPaulo Marquesが答えた。

どのようにして、1つのプロセスだけがファイルにアクセスしていることを確かめているのだろうか?
もしファイルをオープンして、次に別プロセスをフォークすれば、両方は同じファイル記述子を使用してファイルにアクセスすることになる。
多くの理由があるので、あるプロセスがコマンドをデバイスに送っているときに、別のステータス情報を受け取っているかといったようなこの手の問題は、きっちりしておいた方が良いだろう。

Al ViroもPaulo Marquesに同意して答えた。(10時48分のことであるので、ここまで最初の質問から40分程度しか経っていない)

それは違う。 「struct file」についてはプライベートであり、処理されない。そして、(fork()で始まる)多くのものが同じ「struct file」に様々なプロセスからの参照を付けることになる。つまり->open()から返った後すぐに、->release()が呼ばれるまでの間、外部的に明らかに、また潜在的に共有されている、と考えるべきである。

一方でRichard B. Johnsonは、S.Kartikeyan最初の質問を見ただけで、10時41分にはかなり正確に答えたメールをLKMLにポストしていた。

(競合状態があるということは)もちろんだ。しかし、それはただの競合ではない。共用データやハードウェア自体にアクセスする所はどこでも、(あなたのドライバ含めた)あらゆる共有リソースの一つだけに、単一のスレッド実行を許可していることを確かにする必要がある。これは一般に、down()とup()として知られる、セマフォを使って達成できる。
open()呼出しが、それぞれの「struct file」ポインタを用意することに注意することだ。カーネルはそれらを作り上げてはくれないはずだ。
各open()で、プライベートデータのポインタをこの構造体の中で有効にして、各アクセスではそれをプライベートデータに使用できる。このようなプライベートデータは、close()で開放することができる。しかしこれらは、ただの当たり前の事である。ユーザモード・スレッドでは、openしたファイルを共有している!従ってあなたのドライバで、セマフォを使って無い場合には、このようなアクセスを分離する手段を持っていないということを意味する。

LWN.netの管理者として知られる、Jonathan Corbetは、別の観点から答えていた。

ioctl()メソッドで「->private_date」にアクセスしているだけならば、締め出されている。単なるioctl()呼び出しは、ビッグ・カーネルロックによって保護され続け、また同時アクセスができないだろう。
つまりこういう事だ。適正なあなた自身のロック機構を追加し、コードを将来に備えて頑丈にすることは、それほど難しくない。これを直してみてはどうだろうか。LDD3や、他のところにそれをするための多くの情報がある。

実はJonathan Corbetは、先日以下のようなアナウンスをLKMLでしていた。

Linux Device Drivers, Third Edition online

私と、Alessandro RubiniとGreg KHとで書いたLDD3(Linux Device Drivers第3版)が、今やオンラインで利用可能になった。
今のところはPDFフォーマットだけで利用可能であるが、我々が加工作業をすることで、HTMLとDocBookのバージョンがポストされる事になるだろう。この版は2.6.10カーネルを最新としているので、「API changes in the 2.6 kernel series」にその後のAPI変更のリストを保持している。
この本は、(GPL的な) Creative Commons Attribution-ShareAlike 2.0 licenseの基で、自由に再配布できる。
しかしながら、友達がこれのコピーを買うのをすべて止めたりということまではしないでくれ:)

Getting Started With Kernel Hacking

関連する話題をもう一つ取り上げる。少し遡るが、今年1月1日には、 Eugene Kが次のような質問をLKMLに投げていた。

何年かの間私は、Intel86を含む様々なプラットフォームやOSで、OS/Kernelとネットワーク開発をしてきたが、Linuxに全く不慣れである。私のような者がLinuxドライバ開発と、Linuxカーネル内部の両方を学習するための、最適の方法は何だろうか?

まずJim Nelsonは、「http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.htmlを叩くこと。枯れたツリーとオンライン参照の良い選択をしている。また、カーネル管理者プロジェクト(http://www.kerneljanitors.org/)もよいスタート・ポイントだ。」と答えた。

Christoph Anton Mittererらは、Kernelnewbiesはどうだろうか?と薦めた。

Pedro Vendaも応答した。

最近尋ねられた、この手の質問に対するお奨めの本は次の通りだ。 (後の2つは、近々に2.6のカーネルをカバーする新しい版が出るだろう)

Desepak Kotianは、Robert Loveの「linux kernel development」が気に入っていたが、Alessandro Rubini らの「Linux Device Drivers」第3版がいつ出るのかを気にしていた。

これに対してJonathan Corbetは、第3版は彼と、Alessandro Rubiniと、Greg KHが執筆して、出版作業が進んでいると答えた。また、オンラインリリースの準備を進めていることも付け加えた。

Jonathan Corbet

余談であるが、筆者がインターフェース誌7月号で「カーネル2.6のデバイスドライバ」に関する記事を書いた時に、LWN.netの「Porting device drivers to the 2.6 kernel」という記事群を参考にして、加筆修正した表を作成して使用した。その時はLWN.netの管理者宛に、事情を説明して内容の一部引用の許可を貰うメールを書いたのだが、直ぐにJonathan Corbet本人から確認と、快諾の返信が来たのである。