多くの Linux 愛好家は、Linus Torvalds の有名な警告「私たちはユーザー空間を破壊しません」をよく知っていますが、おそらくこの文を聞いた人全員がその意味を認識しているわけではありません。 ABI とは何ですか? ABI は、アプリケーション バイナリ インターフェイスの略です。 ABI の概念を理解する 1 つの方法は、ABI が他の概念とどのように異なるかを考慮することです。多くの開発者にとって、アプリケーション プログラミング インターフェイス (API) の方が馴染みがあります。通常、ライブラリのヘッダー ファイルとドキュメントは、LCTT 翻訳注: 昨日、AlmaLinux は、RHEL との 1:1 互換性を放棄しますが、RHEL との ABI 互換性は維持すると発表しました。 RHEL 上で実行されるソフトウェアは、AlmaLinux 上でシームレスに実行できます。 ABI の概念についてよく理解していない学生もいるかもしれないので、誰でも理解できるようにこの記事を翻訳しました。
カーネル システム コール インターフェイス
」の説明は、「Linux マニュアル セクション 2」にあり、ミドルウェア アプリケーションから呼び出すことができる同様の関数が含まれています。 . C バージョンの mount と sync の関数。これらの関数のバイナリ レイアウトは、Linux ABI の最初の重要な部分です。 「Linux 用の安定した ABI には何が含まれていますか?」という質問に対して、多くのユーザーや開発者は「sysfs (
/sys) と procfs (
/proc) の内容」と答えます。実際、
公式 Linux ABI ドキュメントは主にこれらの
仮想ファイル システムに焦点を当てています。 前のセクションでは、Linux ABI がプログラムでどのように使用されるかに焦点を当てましたが、同様に重要な人的要因については説明していませんでした。以下の図に示すように、ABI の機能には、カーネル コミュニティ、C コンパイラ (GCC
clang など)、およびユーザー空間 C ライブラリの作成が必要です。 (通常は glibc )、および Executable and Linkable Format (ELF) でレイアウトされたバイナリ アプリケーション。
開発コミュニティ内でのコラボレーションTorvalds 氏自身による Linux ABI の安定性保証により、Linux ディストリビューションと個々のユーザーはオペレーティング システムの影響を受けることなくカーネルを独立して更新できます。
Linux 用の安定した ABI がなければ、セキュリティ問題に対処するためにカーネルにパッチを適用する必要があるたびに、オペレーティング システムのほとんどまたはすべてを再インストールする必要があります。バイナリ インターフェイスの安定性が、Linux の使いやすさと広く普及する上で重要な要素の 1 つであることは明らかです。
ターミナル出力
上の図に示すように、カーネル (linux-libc-dev
内) と Glibc ( libc6-dev
) はすべて、ファイルのアクセス許可を定義するビット マスクを提供します。明らかに、これら 2 つの定義セットは一致する必要があります。 apt
パッケージ マネージャーは、パッケージによって提供される各ファイルを識別します。 Glibc ABI の潜在的に不安定な部分は、bits/
ディレクトリにあります。
Linux ABI の安定性保証は、ほとんどの場合に適切に機能します。 コンウェイの法則コンウェイの法則によると、開発プロセス中に発生する厄介な技術的問題は、多くの場合、さまざまなソフトウェア開発コミュニティ間の誤解や意見の相違が原因であり、これらのコミュニティはすべて Linux に貢献しています。上の図に示すように、さまざまなコミュニティ間のインターフェイスは、Linux パッケージ マネージャーのメタデータを通じて容易に想像できます。
Linux ABI は、現在進行中で ゆっくりと発生している「2038 年」の ABI 破損の例を考慮すると、よりよく理解できます。 2038 年 1 月には、古い車両の走行距離計と同じように、32 ビットのタイム カウンタがすべて 0 に戻ります。 2038 年 1 月というとまだ遠いように聞こえるかもしれませんが、現在販売されている IoT デバイスの多くはまだ稼働していると考えて間違いありません。今年設置された スマート メーター や スマート パーキング システム などの一般的な製品は、32 ビット プロセッサ アーキテクチャを使用している可能性があり、ソフトウェア アップデートをサポートしていない可能性があります。
Linux カーネルは、後の時点を表すために 64 ビット time_t
不透明データ型の使用に内部的に切り替えられました。これは、time()
のようなシステム コールの関数シグネチャが 64 ビット システムで変更されたことを意味します。これらの努力の範囲は、データ構造の新しいバージョンと _old バージョンが配置されているカーネル ヘッダー ファイル (time_types.h
など) で明らかにわかります。
走行距離計ロールオーバー
Glibc プロジェクトは 64 ビット時間もサポートしているので、準備は完了ですよね?残念ながら、Debian メーリング リスト での議論によれば、これは事実ではありません。ディストリビューションは、32 ビット システム用のすべてのバイナリ パッケージの 2 つのバージョンを提供するか、インストール メディア用の 2 つのバージョンを提供するかの難しい選択に直面しています。後者の場合、32 ビット時間のユーザーはアプリケーションを再コンパイルして再インストールする必要があります。いつものように、独自のアプリケーションは本当に頭の痛い問題です。
安定した ABI を理解するのは少し難しいです。考慮すべき点は、sysfs の大部分は安定した ABI ですが、デバッグ インターフェイスはカーネルの内部をユーザー空間に公開するため、明らかに不安定であるということです。 Linus Torvalds はかつて「ユーザー空間を壊すな」と言ったことがありますが、通常彼が意味したのは、カーネルのドキュメントやソース コードを読んで確認できるべきシステム プログラマやカーネル エンジニアではなく、「ただ機能したいだけ」の一般ユーザーを保護することです。バージョン間で何が変わったのか。下の図はこの違いを示しています。
安定性の保証
平均的なユーザーが Linux ABI の不安定な部分を操作する可能性はほとんどありませんが、システム プログラマは意図せず操作してしまう可能性があります。 sysfs (/sys
) および procfs (/proc
) のすべての部分は、/sys/kernel/debug
を除いて安定しています。
ユーザー空間に表示される他のバイナリ インターフェイス (/dev
のデバイス ファイル、カーネル ログ ファイル (dmesg
コマンドで読み取ることができる) など) についてはどうでしょうか。ファイル システムのメタデータ、またはカーネルの「コマンド ライン」で提供される「ブート パラメータ」(GRUB や u-boot などのブート ローダーで表示されます)?もちろん、「状況によります」。
Linux システムが起動中にハングするという事実のほかに、ファイル システムをマウントできないことが最も残念です。ファイル システムが有料顧客の SSD 上にある場合、問題は非常に深刻です。古いカーネル バージョンでマウント可能だった Linux ファイルシステムは、カーネルがアップグレードされてもマウント可能であるはずですよね。実際のところ、それは「場合による」のです。
2020 年、負傷した Linux 開発者 がカーネル メーリング リストで苦情を申し立てました :
カーネルは、これをエラーやエラーもなく有効なマウント可能なファイル システム形式として受け入れました。あらゆる種類の警告が表示され、何年もこのように確実に動作しています...私は一般に、既存のルート ファイルシステムのマウントはカーネル<->ユーザー空間またはカーネル<->定義された既存のシステム境界の範囲に属すると常々考えてきました。カーネルによって受け入れられ、既存のユーザー空間で正常に使用されるものによって決まります。カーネルのアップグレードは、既存のユーザー空間およびシステムと互換性がある必要があります。
しかし、問題があります。これらのマウントできないファイル システムは、カーネルによって定義されているが使用されていないフラグに依存する独自のツールを使用して作成されています。このフラグは Linux の API ヘッダー ファイルや procfs/sysfs には表示されませんが、実装の詳細です。したがって、ユーザー空間コードでこのフラグを解釈することは、「未定義の動作」というほぼすべてのソフトウェア開発者を震え上がらせるフレーズに依存することを意味します。カーネル コミュニティが内部テストを改善し、新しい整合性チェックに取り組み始めたとき、「man 2 mount」システム コールが突然、独自形式のファイル システムを拒否し始めました。この形式の作成者は明らかにソフトウェア開発者であったため、カーネル ファイルシステムの保守者から共感を得ることができませんでした。
工事標識には、作業員が木の上で作業していると書かれています
/dev
ディレクトリ内のファイル形式は安定していることが保証されていますか?または不安定ですか? dmesg コマンドは、ファイル /dev/kmsg
からコンテンツを読み取ります。 2018 年、開発者は dmesg 出力のスレッド を実装し、カーネルが「同時実行による中断や干渉を受けることなく、一連の printk() メッセージをコンソールに出力できるようにしました」他のスレッドの
printk()"。いいですね!スレッド化は、
/dev/kmsg 出力の各行にスレッド ID を追加することで実現されます。注意を払っている読者であれば、この変更により
/dev/kmsg の ABI が変更されることがわかります。つまり、このファイルを解析するアプリケーションもそれに応じて変更する必要があります。多くのディストリビューションは新機能を有効にしてカーネルをコンパイルしないため、
/bin/dmesg のほとんどのユーザーはこれに気付かないかもしれませんが、この変更により
GDB デバッガ を読み取る機能が壊れます。カーネルログ。
/dev/kmsg 形式をサポートするために更新する必要があるコードは、カーネル独自の Git ソース コード リポジトリの「ツリー内」部分にあるため、これは実際には当てはまりません。通常のプロジェクトの場合、単一のコードベース内のプログラムが連携できないことは明らかなバグであるため、GDB がスレッド化された /dev/kmsg
で動作できるようにする パッチがマージされました。
BPF は、実行中のカーネルでリアルタイムに監視し、構成することもできる強力なツールです。 BPF は元々、システム管理者がコマンド ラインからその場でパケット フィルターを変更できるようにすることで、リアルタイムのネットワーク構成をサポートするように設計されました。 Alexei Starovoitov らは、任意のカーネル関数のトレースを可能にするために BPF を大幅に拡張しました。トレースは明らかに開発者の領域であり、一般ユーザーの領域ではないため、明らかに ABI 保証の対象ではありません (ただし、bpf() システム コール には他のシステム コールと同じ安定性が保証されています)。一方、新しい機能を作成する BPF プログラムは、カーネルを拡張する事実上の標準手段としてカーネル モジュールを置き換える可能性を提供します。カーネル モジュールは、デバイス、ファイル システム、暗号化、ネットワーキングなどを適切に動作させるものであり、「動作させたいだけ」という平均的なユーザーが依存する機能であることは明らかです。問題は、ほとんどのオープンソース カーネル モジュールとは異なり、BPF プログラムは伝統的にカーネル ソース コードに含まれていないことです。 2022 年の春、幅広いヒューマン インターフェイス デバイス (マウスやキーボードなど) にデバイス ドライバー パッチの代わりにミニ BPF プログラムを使用するという
提案が注目されました。サポート。 白熱した議論が続きましたが、問題は明らかに
オープンソース サミットでの Torvalds のコメントで解決されました: 彼は、「通常の (カーネル開発者ではない) ユーザーが使用する実際のユーザー空間ツール」を壊す場合は、eBPF が使用されているかどうかに関係なく、それを修正する必要があると指摘しています。 カーネル更新後も BPF プログラムが動作することを望む開発者は、カーネル ソース コード リポジトリ内のまだ指定されていない場所にプログラムをコミットする必要があるというコンセンサスが得られつつあるようです。 。 BPF と ABI の安定性に関してカーネル コミュニティがどのようなポリシーを採用するかに注目してください。 Akkana Peck、Sarah R. Newman、Luke S. Crawford に感謝します。マテリアルのバージョン。コメント。
以上がLinux ABI について 10 分で学ぶの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。