Rust for Linuxプロジェクトの一環で、Rust for Linuxドライバーを開発できるようにすることを目的として、GoogleのAndroidチームは、Rustを使用することで得られるメリットの評価に取り組んでいる。
Rust for Linuxは、約1年前にLKML(Linuxカーネルメーリングリスト)でMiguel Ojeda氏によって発表された。それは、Linuxビルドシステムを拡張することでLinuxカーネル開発に第二の言語を導入する試みとしてであった。具体的には、このプロジェクトはRustを使ってドライバーや他の「leaf」カーネルモジュールを作成できるようにすることを目指している。しかし、カーネルコアや主要なカーネルサブシステムは対象ではない。
Rustは、カーネルを実装するための実用的な言語としてCと共に加わる準備ができていると感じています。これにより、特権コードの潜在的なバグとセキュリティの脆弱性の数を減らす助けとなります。同時に、コアカーネルをうまく操作し、そのパフォーマンス特性を維持できます。
Linuxビルドシステムの拡張は全体像の一部にすぎないと、Androidチームで働くWedson Almeida Filho氏は言っている。実際、RustがLinuxカーネル開発の第1級市民であるためには、カーネルのC実装からRustで記述されたコードを安全かつ効率的に呼び出すための相互メカニズムも必要である。
RustがLinuxドライバー開発者が正しく安全なコードを書くのにどのように役立つかを示すために、Almeida Filho氏は彼の記事で、CとRustのシンプルなセマフォ文字デバイスの2つの実装を比較している。これにより、Rustが保証される前提において、ドライバーの実装が共通的に実行するいくつかのタスクを正確に特定できる。
たとえば、Rustの所有権モデルを利用して、RustオブジェクトをCコードに渡し、この呼び出し関数をRustで実装し、オブジェクトの所有権をRust側に戻すことができる。これを行うと、Cコードが正しく記述されている限り、正しいライフタイム管理が実施される。
Rustのプロビジョニングが役立つもう1つの領域は、不変の参照の使用である。たとえば、不変のself
を渡すことは、いわゆる内部可変性が使用されない限り、そのオブジェクトが変更されるのを防ぐ。これには、ミュータントコードをMutex<T>
またはSpinLock<T>
でラップする必要がある。これらは、コンパイル時にチェックされ、開発者が最初にロックを取得せずに誤って状態を変更してしまうことを防ぐことができる。
Rustによって、デバイス固有の特性への不変の参照を使って、デバイスごとの共有状態をより安全に管理できるようにもなる。その参照は、そのデバイスに関連付けられているすべてのオブジェクトに渡される。
Almeida Filho氏は、カスタムioctlハンドラーを実装するときに開発者がRustから得ることができる多くの利点についても説明している。特に、ディスパッチャーを使用して、低レベルのメモリを処理する際の典型的なエラーを防ぐメモリアクセスヘルパーを自動的に作成する。エラーには、バッファーオーバーフローや読み取り/書き込みミキシングなどがある。
これらはほんの一例である。Linuxドライバーを作成する際のRustの利点を証明するために、Androidチームは、Binder IPCドライバーをRustに移植する取り組みを行っている。Binder IPCドライバーは、Androidのプロセス間通信(IPC)に使用され、2015年にLinuxカーネルで受け入れられた。この取り組みは、すでに良い状態となっている。
現時点では、我々はBinderに必要なほぼすべての汎用カーネル機能を持っており、安全なRustの抽象化により、きちんとラップされています。
Almeida Filho氏の記事には、ここに要約されているものの詳細が含まれているので、興味がある場合は忘れずに読んでください。