web-dev-qa-db-ja.com

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

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

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

続けて、Linuxコンベンションと「Unixコンベンション」の両方をサポートするFreeBSDについて述べています

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

Linuxの方法がかさばり、遅くなるのは私には奇妙に思えます。 2つのオプションがあるように見えますが、

  • 保存する必要のあるレジスタだけを保存します。どちらか
    • システムコールによって破壊される可能性のある揮発性レジスタ(私の知る限りecx
    • または、syscalleaxecxedxesiediebp
  • スタック上のカーネルへの引数を100%保存します。

FreeBSDのものはLinuxコンベンションの最悪のケースシナリオのように思われるでしょう。何が欠けていますか? FreeBSDの慣習(彼らは「Unixの方法」と呼んでいます)はどのようにかさばらず、より速くなりますか?

3
Evan Carroll

私の意見では、これは本当に著者の意見に要約されます。

FreeBSD(“ Unix”)規則では、スタックに引数をプッシュし、EAXでシステムコール番号を指定し、割り込み0x80を呼び出します(スタックに追加のオペランドが呼び出されることを想定しているため、別の機能)。

Linux i386規約では、引数を適切なレジスタに配置し、割り込み0x80を呼び出します。

かさばる/遅い引数は、おそらくLinuxの規則では、callerがレジスターの使用を処理する必要があるという事実に由来します。システムコールが、呼び出し元が気にする値を含むレジスターに引数を必要とする場合、それらを保持する必要があり、その結果、追加のレッグワークが発生します。 Cライブラリのこの例を参照 。この例では、システムコールにはEAX、EBX、EDX、EDI、およびESIの値が必要です。ただし、呼び出し元はEBX、EDI、およびESIの保持のみを考慮しているため、それらをスタックにプッシュするだけです。一般的なケースは かなり複雑です (ただし、これはC言語とアセンブリ言語の混合を処理し、すべての場合に最適なコードを生成しようとした結果でもあります)。ただし、アセンブリ言語で記述している場合は、これはあなたが言及しているサイトのポイントですが、それほど問題にはなりません。

それは6ダースと6ダースだと思われます。FreeBSDの慣習では、すべての場合にスタックにプッシュします。Linuxの慣習では、何をしているのかに応じてスタック(または他の場所)にプッシュします呼び出しサイト。レジスタですべての計算を実行できるため、Linuxの規則によりコードの高速化が可能になると主張できます... Rob が指摘するように、Linuxでは、レジスタは(struct pt_regsインスタンスは、システムコールを処理するC関数に引数を提供するために使用されるため、全体のコストはLinux側の方がFreeBSD側よりも大きくなります。

いずれにせよ、システムコール自体を実行するコストを考えると、システムコールに関するスタックまたはレジスタベースのコードについて話すときにパフォーマンスについて議論することは、かなり衒学的に思えます。もちろん、節約されたサイクルは絶対的には良好ですが、相対的な改善はごくわずかです。

9
Stephen Kitt