カーネルが知らない間にプロセスは新しいプログラムを実行できますか?通常、プログラムが実行されているとき、カーネルはシステムコール(例:exec()またはfork())を受け取った後に独自のプロセスを提供します。この場合、すべてがカーネルを通過し、最終的にELFハンドラなどを使用してプログラムが起動します。もちろん、実際には新しいプログラムを実行するときに別々のプロセスが必要ですが、それが必要でない場合はどうなりますか?プログラム/プロセスxhathatは実行可能なバイナリをファイルシステム(たとえば、システムコールを介して)から独自の仮想メモリ領域に転送し、そのプロセス内で実行を開始できますか?この場合、カーネルはプログラム/プロセスxhathatが何かをしていることだけを知っていますが、プログラムxhathatが実行されるという事実は個別にはわかりません。
「カーネルは知らない」というのは…それはどういう意味ですか?
私が意味するのは、カーネルが実際に「プログラムを起動/実行」しないことです(通常、カーネルはバイナリであるかshebangを含む解釈されたスクリプトであるかにかかわらず、常にこれを行います)。間接的にのみ可能です。はい、大容量ストアからこのxhathatプロセスのメモリ領域に新しいプログラムをロードしますが、起動/実行せず、起動/実行も認識しません。 exec()やfork()など、さまざまな起動/実行カーネルシステムコールを実行しません。たとえば、カーネルが意識的にプログラムを起動しないと、そのプログラムはプロセスにも表示されません(xhathatプロセス内の「プロセス/実行」にすぎないため)。追いつくことができますか?私が知る限り、バイナリコンパイルプログラム(もちろん解釈されたプログラム)も可能です。私はbashやsystemd、またはプログラム/プロセスを「起動/実行」するすべてが、通常、カーネルが実際に起動/実行(または前述のようにshebangスクリプト)を実行することに気づいたときにのみこれを考えました。ところで、この事実を知ってから、必ずこれをしなければならないのでしょうか? という気がしました。私はあなたの答えを受け入れます。必ずしもこれを行う必要はありません。もちろん、一般的にこれを行う方が良いです(カーネルはすべてのプログラム/プロセスを開始します)。そしてそれが完了しました。
ところで、私が説明したタスクを実行するには(簡単に言えば)どのコアが必要ですか?頭に浮かぶ唯一のことは、この新しいプログラムを大容量リポジトリからダウンロードすることですが、プログラムがすでに中央リポジトリにあり、大容量リポジトリから別々にダウンロードする必要がない場合はどうなりますか?カーネルとの対話なしに、プロセスは新しいプログラム/「プロセス」の実行を直接開始できますか?
答え1
はい、可能です。すでに実行されているプロセスは、新しいプログラムをプロセスの仮想アドレス空間の適切な場所にロード(またはマッピング)し、必要に応じて動的ローダをロードし、スタックに必要なデータ構造を設定してから、新しいプログラムの場所にジャンプする必要があります。メモリのエントリポイントです。 (これらの操作の多くはカーネルに関連していますが、新しいプログラムをロードすることとは関係ありません。)
fork
プロセスはカーネルの助けを借りずにまったく新しいアドレス空間を作成することはできませんが、ランチャーは新しいプログラムが実行された後に制御を取得することを期待してはいけません。 。アドレス空間。
バラよりグルグのUserland Execの設計と実装より詳細な説明が必要です。
答え2
はい、いいえ...
つまり、簡単に言えば、多くのプログラミング言語が解釈されます。したがって、最初のプログラムがPythonインタプリタで実行されるPythonプログラムの場合は、別のファイルをインポートして実行するだけです。
インタプリタの代わりにバイナリプログラムを使用して同じことを行うのは少し難しいです。
「カーネルは知らない」というのは…それはどういう意味ですか? 2番目のプログラムはどこから来たのですか?ディスクからロードしましたか? (カーネルはこれを行います...)ネットワークからロードしていますか? (カーネルもこれを行います。)実行可能ページを置き換えたい場合、ほとんどの場合、最新のカーネルは実行可能コードを含むページまたは実行されるコードを含む書き込み可能ページを作成できません。 。新しい内容を解釈するよりも、コードページでは、カーネルはこれらのページをロードして実行可能にすることに関与する必要があります。
プロセスは、カーネルの直接的な介入なしに他のプロセスを開始できません。カーネルを大量に使用せずにそれ自体を置き換えたり、より多くの実行コードを追加したりできますが、そのページをインポートするために一種のI / Oを実行する必要はありません。
カーネルは、次の理由で実行中のプロセスを「知っています」。
- ページテーブル権限の一部として、プロセスで実行できるメモリのページを知っています。これは簡単にバイパスできません。
- 通常、これらの実行可能ページはメモリにマップされ、要求に応じてページングされるため、どのファイルから出てくるのかがわかります。つまり、カーネルは要求時にディスク上のファイルのページをメモリにロードします。これは、ページがすでにメモリにキャッシュされていても、ページキャッシュシステムの一部として引き続き発生します。
- カーネルは、初期実行可能ファイルの起動に使用された名前を知っています。
- カーネルは、プロセスの開始時にコマンドラインと環境を知っています。プロセスはほとんどのシステムでこれを編集できますが、
- カーネルは、どのファイルが開いていて赤であるかを知っています。
上記のほとんどは、ps
すべてのUNIXシステムでこのコマンドを使用して表示できます。上記のすべては/proc/
Linuxシステムで利用可能です(ページテーブル情報を除く)。
それでは、exec()を使用せずに実行できますか?確かに!どのような方法でカーネルを介さずに実行できますか?まさか。