FreeBSDとLinux:カーネル呼び出しルールのパフォーマンス

FreeBSDとLinux:カーネル呼び出しルールのパフォーマンス

~からint80h.org、FreeBSDアセンブリ言語チュートリアル

[Linux 呼び出し] ルールは、少なくともアセンブリ言語プログラミングに関する限り、Unix 方式に比べて大きな欠点があります。カーネルを呼び出すたびにレジスタをプッシュしてポップする必要があります。これにより、コードが大きくなり、遅くなります。

FreeBSDがLinuxルールと「Unixルール」をサポートしていると言ってください。

FreeBSD用に特別にコーディングする場合は、常にUnixルールを使用する必要があります。より高速でグローバル変数をレジスタに保存でき、実行可能ファイルにブランドを割り当てる必要がなく、Linux エミュレーションパッケージを強制的に実行する必要もありません。ターゲットシステムにインストールする必要があります。

私はLinuxのアプローチがより薄くて遅いという事実が奇妙だと思います。選択肢は2つのようですが、

  • 保存する必要があるレジスタのみを保存してください。
    • システムコールによって破損する可能性のある揮発性レジスタ(私の知る限りecx
    • あるいは、レジスタを生成するために適切なパラメータをカーネルに転送する必要があります(syscallおそらくeax、、、、、、、)。ecxedxesiediebp
  • カーネルパラメータを100%スタックに保存します。

FreeBSDのようです。最も悪いLinuxコンベンションケースのシナリオ。私は何を見逃していますか? FreeBSDルール(「Unix方式」と呼ばれる)は、どのように小さくて高速化できますか?

ベストアンサー1

私の考えでは、執筆者の視点が本当に正しいようです。

FreeBSD("Unix")ルールでは、引数がスタックにプッシュされ、システムコール番号がに割り当てられ、割り込みEAX0x80が呼び出されます(別の関数で呼び出しが予想されるため、スタックに追加のオペランドを使用して)。

Linux i386ルールでは、パラメータを適切なレジスタに配置し、割り込み0x80を呼び出します。

大きくて遅い議論は、おそらくLinuxの規則によると、次のような事実に由来します。訪問者レジスタの使用を処理する必要があります。システムコールに呼び出し元が関心のある値を含むレジスタのパラメータが必要な場合は、そのパラメータを保存する必要があるため、追加の作業が必要です。Cライブラリの例を見る。この例では、システムコールにはEAX、EBX、EDX、EDI、およびESIの値が必要ですが、呼び出し側はEBX、EDI、およびESIの保持にのみ興味があるため、その値をスタックにプッシュします。一般的な状況はかなり複雑です(しかし、それはCとアセンブリの混合を処理し、あらゆる状況で最高のコードを生成しようとした結果でもあります。)しかし、言及したサイトのポイントであるアセンブリとして書くときはそうではありません。それでなくても大きな問題だ。

私の考えには6つの半分です。 FreeBSD ルールではすべての場合にスタックにプッシュし、Linux ルールでは実行中の呼び出しサイトに応じてスタック (または他の場所) にプッシュします。すべての計算をレジスタで実行できるため、Linuxルールを使用すると、より高速なコードが可能であると言うこともできます。ロブstruct pt_regsただし、Linuxでは最終的にレジスタがプッシュされるため(システムコールを処理するC関数に引数を提供するために構築されたインスタンス)、Linux側の総コストがLinux側よりも高いことが指摘されています。 FreeBSD側。

それにもかかわらず、システムコール自体を実行するためのコストを考慮すると、システムコールに関連するスタックまたはレジスタベースのコードについて話すときのパフォーマンスについて議論するのはやや賢明なようです。すべてのサイクル削減は絶対的な意味では確かに良いですが、相対的な改善効果は小さいです。

おすすめ記事