文字列の比較は遅いですが、インデックス付けは速く、私が書いているスクリプトの多くがbashにあるので質問します。 bashは、私が知っている限り、すべての実行可能呼び出しに対して完全な文字列検索を実行します。これらすべてのls
' とgrep
' は、各ステップで文字列検索を実行しなくても少し速くなります。もちろん、コンパイラの最適化を探ります。
とにかく、inode番号だけを使用してLinux上でプログラムを直接呼び出すことはできますか?
答え1
最も簡単な答えは「いいえ」です。
より長い答えは、LinuxユーザーAPIがinode番号を使用してファイルにアクセスする方法をサポートしていないことです。 inode番号への唯一のアクセスは通常、inode番号を公開するstat()システムコールを介して行われます。これは、2つのファイル名が同じファイルかどうかを識別するのに役立ちますが、他のファイルには役立ちません。
inodeを介してファイルにアクセスすると、inodeに関連付けられているファイルを含むディレクトリの権限がバイパスされるため、セキュリティに違反します。
最も近い方法は、ファイルハンドルを開いてファイルにアクセスすることです。ただし、ここでもプログラムを実行することはできず、パスを介してファイルを開く必要があります。 (説明で述べたように、この機能はセキュリティ上の理由から* atシステムコールの残りの部分と一緒にLinuxに追加されましたが、移植可能ではありません。(標準は進化しています)。
inode番号を使用して(デフォルトでファイルシステムをキャッチし、statを使用して)ファイルを見つけて正常に実行する方法もありますが、パス名を介してファイルにアクセスするよりもはるかにコストがかかるため、これは望むものとは反対です。そのコストを排除しないでください。
しかし、Linuxはすでに内部inodeルックアップに対して多くの最適化を実行しているため、この種の最適化について心配する必要はほとんどありません。また、シェルは伝統的に実行可能ファイルのパスの場所をハッシュしているため、$PATH
毎回すべてのディレクトリでそのファイルを見つける必要はありません。
答え2
はい可能ファイルのinodeを介してファイルを実行します。
find / -inum 242 -exec {} \; -quit
ただし、パフォーマンスが問題になり、上記はパフォーマンスではありません。 inodeを含むファイル(複数のファイルがあるかもしれません)を見つけるためにディレクトリ構造を探索するだけでなく、後でinode番号がパスとして解決され、そのパスが実行のためにカーネルに提供されます。しかし、なぜ?
カーネルはすべて、カーネル関数をラップする一連のexec関数(など)を公開execl
します。現在のプロセスイメージをコンテンツを読み取り、起動した新しいプロセスイメージに置き換える機能です。execvp
execve
与えられたファイルパスで。だからすべてカーネルが提供するプログラムの実行方法をパスで知らせる必要があります。ファイルパスをエントリポイントとして使用すると、ファイルパスに関連するすべてのアクセス制御の利点が得られるため、「パス別」APIはLinuxでプログラムを実行するための唯一のAPIです。
ただし、面倒で、あらゆる環境で動作が保証されないメカニズムがあるため、プログラムを呼び出すことができます。記憶から。メモリ内のすべてはディスク上のものよりも速いので、プログラムをできるだけ早く実行する方法が問題の中心になります。
2002年初め、(有名な)ハッカーgrugqがuserland execの概念を導入しました。これはシェル関数ではありません。ユーザーモードで作成されたカーネル関数によって実行されるすべてのステップのシミュレーションexec
。execve
これは、一般的なアクセス制御メカニズムの外部でプログラムを実行できるため、自分のアクティビティを隠したいハッカーに最適ですexecve
。
このメソッドを実装するには、アドレス空間のクリーンアップ、動的リンカーのロード(必要な場合)、スタックの初期化などを行う複数のヘルパーが必要です。さらに、メカニズムを使用するには、必要なコードを特定の種類のメモリにロードする必要があります。
このようなことを難しくする対策もあるが、不可能なものではない。必要なのは、ターゲットシステムにページソートメモリ、メモリを実行可能としてマークする機能、メモリ内の特定のポイントにジャンプする機能があることです。これらの要件は通常、次のように解釈されます。これをCで記述し、SELinuxが存在しないか、SELinuxが完全に有効になっていないシステムで使用する必要があります。ここでは実装の詳細については説明しませんが、直接ナビゲートできるリンクを提供します。
したがって、Linuxシステムが上記の要件を満たしている場合は、次の方法でメモリからコードを実行できます。
- コードをメモリ内の1つの場所にロードします。初期除去の一部として、悪意のある行為者が必要なコードをメモリにサイドロードしたが、inode方式で実行したい場合は、次のことができます。
find / -inum 242 -exec cat {} \;
- userland execメカニズムを呼び出して、エントリポイントを手順1でプログラムを保存したメモリアドレスに設定します。
- 利益
カーネル、ファイルシステム、およびシェルはすべて調整され、プログラムのルックアップと実行がタスクを実行するために必要な合計オーバーヘッドの小さな部分です。メモリにプログラムをロードしてそこで実行することは、実際には平均ユースケースの範囲には含まれていないので、楽しんでいない場合は、試すのに時間を費やす前にパフォーマンスをベンチマークする必要があると言いたいと思います。 。
引用:
答え3
これはi-nodeの質問に対する直接的な答えではありませんが、シェルスクリプトで標準のユーティリティパスを見つけるのを防ぐのに役立ちます。
忙しい箱多くの標準のUnixユーティリティを置き換えるすべてのツールを、組み合わせたサイズよりはるかに小さい単一の実行可能ファイルにまとめたプログラムです。これは、ディスクサイズが非常に重要な組み込みの世界で非常に人気があります。一般的なBusyBoxベースのシステムでは、sh
および
ls
はgrep
すべてへのシンボリックリンクですbusybox
。したがって、ls
呼び出すシェルスクリプトは自分自身を2回だけ呼び出しgrep
ますbusybox
。
BusyBoxには「スタンドアロンシェル」という実験的な機能があります。この機能が有効になっていると、シェルとして機能するBusyBoxは、実装しているユーティリティに対してパスルックアップを実行しません。代わりに、/proc/self/exe
正しいパラメータを使用して独自に実行されます。たとえば、を呼び出すシェルスクリプトを実行している場合は、検索する代わりにgrep
実行されます。カーネルにはまだパスルックアップがありますが、どのユーティリティを呼び出すかは常に同じで、実行可能イメージはすでにメモリにあるため、ロードする必要はありません。grep
$PATH
/proc/self/exe grep <arguments>
/proc/self/exe
しかし、BusyBoxには多くの最適化機能があります。サイズ別速度ではなく数マイクロ秒を節約することに興味がある場合は、おそらく最善の選択ではありません。また、前述のように、「スタンドアロンシェル」機能は実験的とマークされています。
答え4
ノード番号のみを使用してLinuxでプログラムを直接呼び出す方法はありますか?
いいえ、そうではありません。単純な理由で単数形を使用しています。ㅏ計画」と「それ「inode番号」を使用しますが、inodeは一意ではありません。システムに同じinode番号を持つ複数のファイルがある可能性があります。
したがって、単純な常識に基づいてできる最善の方法は、「inode番号のみを使用して1つ以上のプログラムセットを直接呼び出す」ことです。できない移動する特定プログラムグループからプログラムを選択するために、そのプログラムに関する追加の識別情報を必要とせずにプログラム。
もちろん、識別情報の1つはパスです。この時点で再び原点に戻ります。