24

プログラムは、ある言語からASM->マシンコード(直接実行可能)にコンパイルされます。これがプラットフォームに依存すると言われる場合、形成されたバイナリは、x86、x86-64などの同じ命令セットアーキテクチャを備えたCPUでのみ(正しく)実行されることを意味します。ISAの違いにより、他のプロセスで(誤って)実行される場合と(まったく)実行されない場合があります。右?

さて、バイナリの概念は私を混乱させています。すべては「機械語コード」と「CPU」に関するものです。OSはどこで機能しますか?つまり、コンパイルされたバイナリには、メモリにロードされたときにCPUへの直接命令が含まれています。&CPUは一度に1つの命令を実行します。プロセス管理のリンクテキストを除いて、オペレーティングシステムの役割はどこにもわかりませんでした。オペレーティングシステムに関係なく、同じISAのCPUで実行されている必要があります。右?

しかし、そうではありません。Windowsマシンでx86へのコードをビルドした場合。Macx86マシンまたはLinuxx86マシンでは動作しません。

ここに何かが足りません。私の混乱を解消してください。

4

9 に答える 9

19

手始めに、最近のCPUには(少なくとも)2つのモードがあります。オペレーティングシステム自体のコアを実行するモード(「カーネルモード」)とプログラムを実行するモード(「ユーザーモード」)です。ユーザーモードの場合、CPUは多くのことを実行できません。

たとえば、マウスクリックは通常、ユーザーモードではなく、カーネルで認識されます。ただし、OSはイベントをユーザーモードにディスパッチし、そこから正しいプログラムにディスパッチします。逆の場合も協力が必要です。プログラムは画面に自由に描画できませんが、OSとカーネルモードを通過して描画する必要があります。

同様に、プログラムを開始する行為は通常、協力です。OSのシェル部分もユーザーモードプログラムです。マウスクリックを取得し、プロセスを開始するためのマウスクリックであると判断します。次に、シェルはOSのカーネルモード部分にそのプログラムの新しいプロセスを開始するように指示します。

カーネルモードが新しいプロセスを開始する必要がある場合、最初にブックキーピング用のメモリを割り当て、次にプログラムのロードに進みます。これには、バイナリから命令を取得するだけでなく、プログラムをOSに接続することも含まれます。これには通常、バイナリのエントリポイント(通常はint main(int argc, char** argv))、およびプログラムがOSを呼び出したいすべてのポイントを見つける必要があります。

オペレーティングシステムが異なれば、OSとプログラムを接続する方法も異なります。その結果、ロードプロセスが異なり、バイナリのファイル形式も異なる可能性があります。絶対ではありません。バイナリのELF形式は多くのオペレーティングシステムで使用されており、Microsoftは現在のすべてのオペレーティングシステムでPE形式を使用しています。どちらの場合も、フォーマットはバイナリの正確なフォーマットを記述しているため、OSはプログラムをOSに接続できるかどうかを判断できます。たとえば、Win32バイナリの場合、PE形式になるため、Linuxはそれをロードしません。Windows2000は、Windows7-64と同様にロードします。一方、Win64バイナリもPE形式ですが、Windows2000はそれを拒否します。

于 2009-10-21T08:48:15.113 に答える
13

01010110011はx86で何かを意味し、ARMで何かを意味するため、他のプロセッサでは実行されません。x86-64はx86と下位互換性があるため、x86プログラムを実行できます。

バイナリは、OSが理解できる特定の形式です(windows = PE、mac / linux = ELF)

通常のバイナリでは、OSがそれをメモリにロードし、いくつかのフィールドに特定の値を入力します。これらの「特定の値」は、kernel32やlibcなどの共有ライブラリ(dllなど)に存在するAPI関数へのアドレスです。バイナリ自体はハードドライブ、ネットワークカード、ゲームパッドなどにアクセスする方法を知らないため、APIアドレスが必要です。プログラムはこれらのアドレスを使用して、OSまたは他のライブラリに存在する特定の機能を呼び出します。

本質的に、バイナリには、すべてを機能させるためにOSが埋める必要のある重要な部分がいくつか欠けています。OSが間違った部分を入力すると、それらが相互に通信できないため、バイナリは機能しません。これは、user32.dllを別のファイルに置き換える場合、またはmacosxでLinux実行可能ファイルを実行しようとした場合に発生します。

では、libcはどのようにしてファイルを開く方法を知っているのでしょうか。

libcは、OSコア機能への低レベルアクセスであるsyscallsを使用します。これは、特定のCPUレジスタにデータを入力してから、割り込み(特別なCPU命令)をトリガーすることによって行うことを除けば、関数呼び出しのようなものです。

では、OSはどのようにしてファイルを開く方法を知っているのでしょうか。

これは、OSが行うことの1つです。しかし、ハードドライブと通信する方法をどのように知るのでしょうか。そのようなものがどのように機能するかは正確にはわかりませんが、OSがBIOS関数にマップされている特定のメモリ位置を読み書きすることによってこれを行うと思います。

では、BIOSはどのようにしてハードドライブと通信する方法を知っているのでしょうか。

私もそれを知りません、私はそのレベルでプログラミングをしたことがありません。BIOSがハードドライブコネクタに配線されており、ハードドライブと「SATA」を通信するために1と0の正しいシーケンスを送信できると思います。たぶん「この分野を読む」などの簡単なことしか言えないでしょう

では、ハードドライブはどのようにしてセクターの読み取り方法を知るのでしょうか。

私はこれをまったく知らないので、ハードウェアの人に続けさせます。

于 2009-10-21T08:48:43.770 に答える
8

ふたつのやり方:

何よりもまず、答えは「システムコール」です。I / O、デバイスとの対話、メモリの割り当て、プロセスのフォークなどを行う必要がある関数を呼び出すときは常に、その関数は「システムコール」を行う必要があります。syscall命令自体はX86の一部ですが、使用可能なシステムコールとそれらに対するパラメーターはOS固有です。

プログラムがシステムコールを行わない場合でも(これが可能かどうかはわかりませんが、確かにあまり役に立ちません)、マシンコードをラップする形式はOSによって異なります。そのため、exe(PE)とLinux実行可能ファイル(通常はELF)のファイル形式が異なります。そのため、Linuxではexeファイルは実行されません。

編集:これらは低レベルの詳細です。より高いレベルの答えは、ファイル、コンソール/ GUI、メモリの割り当てなどにアクセスする必要があるものはすべてOS固有であると言うことです。

于 2009-10-21T08:31:07.237 に答える
3

OSは、ハードウェアレベルで抽象化された「サービス」にアクセスしようとすると機能します。たとえば、ファイルシステムと呼ばれる「データベース」内のファイルを開き、乱数を生成します(すべての最新のOSにはこの機能があります)。

たとえば、GNU / Linuxでは、レジスタに入力し、int 80hを呼び出して「サービス」(実際には「syscall」と呼ばれます)にアクセスする必要があります。

実行可能ファイルにはさまざまなファイル形式があるため、プログラムは別のOSで実行されません。たとえば、WinにはCOFF / PEがあり、LinuxにはELFファイル形式があります(他のファイル形式と同様に、これには「メタデータ」も含まれます。 HTML(またはSGML)ファイル形式)。

于 2009-10-21T08:31:51.540 に答える
2

OSは、(a)マシンコードが実行される環境、および(b)標準サービスを提供します。(a)がないと、コードは最初から実行されません。(b)がないと、すべてを自分で実装し、ハードウェアに直接アクセスする必要があります。

于 2009-10-21T08:32:08.420 に答える
1

高水準言語によって生成されたマシン命令は、システムコールを含む、呼び出しを提供するライブラリの呼び出し規約に適しています(ただし、これらは通常、どこかのユーザースペースライブラリにラップされているため、システムコールの実行方法の詳細必要ないかもしれません)。

さらに、いくつかの例外を除いて、ターゲット命令セットアーキテクチャに適しています(たとえば、ポインタサイズ、プリミティブ型、構造体レイアウト、C ++でのクラス実装などに関する仮定に注意する必要があります)。

ファイル形式は、オペレーティングシステムがコードをプロセスとして実行し、プロセスを必要な状態にブートストラップできるようにするために必要なフック/公開されている関数とデータを指示します。WindowsでのC/C ++の開発に精通している場合、サブシステムの概念によって、ブートストラップのレベル、提供されるリソース、およびエントリポイントの署名(通常main(int, char **)はほとんどのシステム)が決まります。

高水準言語、命令セットアーキテクチャ、および実行可能ファイル形式の選択が、特定のシステムでバイナリを実行する機能にどのように影響するかについて、いくつかの良い例があります。

アセンブリ言語は、特定のISA用にコーディングする必要があります。これらは、CPUタイプのファミリーに固有の命令を使用します。これらのCPUが特定の命令セットをサポートしている場合、これらの命令は他のCPUファミリで機能する可能性があります。たとえば、x86コードは、amd64オペレーティングシステムである程度機能し、x86オペレーティングシステムを実行しているamd64CPUで確実に機能します。

Cは、ISAの詳細の多くを抽象化します。いくつかの明らかな例外には、ポインターのサイズとエンディアンが含まれます。、、、などprintfのさまざまなよく知られたインターフェイスが、libcを介して期待されるレベルで提供されます。これらには、これらの呼び出しを行うために予想されるレジスタとスタックの状態が含まれ、Cコードが変更なしでさまざまなオペレーティングシステムとアーキテクチャで動作できるようにします。他のインターフェイスは、直接、またはプラットフォーム固有を期待されるインターフェイスにラップしてCコードの移植性を高めることにより、提供できます。mainfopen

Pythonやその他の同様の「仮想化」言語は、さらに別のレベルの抽象化で動作します。また、いくつかの例外を除いて、特定のプラットフォームに存在しない機能や文字エンコードの違いなど、多くのシステムで変更なしで実行できます。これは、パフォーマンスと実行可能サイズを犠牲にして、多くの異なるISAとオペレーティングシステムの組み合わせに統一されたインターフェイスを提供することによって実現されます。

于 2009-10-21T09:47:51.767 に答える
0

また、OSがプログラムの起動を処理することを追加したいと思います。プロセススペースを準備し、初期化して、プログラムを開始し、プログラム命令をロードして、プログラムに制御を与えることができるようにします。

于 2009-10-21T08:56:31.083 に答える
0

OSは、特定の機能とハードウェアにアクセスするためのツールとAPIを提供します。

たとえば、Microsoft Windowsでウィンドウを作成するには、ウィンドウを作成するためのOSのDLLが必要です。

APIを自分で作成する場合を除いて、OSが提供するAPIを使用します。そこでOSが活躍します。

于 2009-10-21T08:30:22.497 に答える
0

アナロジー:

あなたが他の国から執事を雇ったとしましょう。彼はあなたが言う言葉を理解していないので、あなたはスタートレックのような翻訳装置を手に入れます。今、彼はあなたの高級言語を理解することができます。なぜなら、あなたが話すとき、彼は彼自身の(かなり粗雑な)言語を聞くからです。

ここで、彼にAからBまで歩いてもらいたいとします。彼の足や足に直接話しかけるのではなく、彼に顔を向けてもらいます。彼は自分の体をコントロールしています。1)あなたがあなたの要求を適切に伝え、2)彼がそれが彼の雇用義務に該当すると決定した場合、彼はAからBに移動します。

これで、最後の使用人と同じ国から新しい使用人を取得します(新しいスタートレック翻訳者を購入したくないため)。彼にもAからBまで歩いてもらいたい。しかし、この使用人はあなたに大声で話し、尋ねながらお願いしますと言うことを要求します。彼はより柔軟なので、これに我慢します。必要に応じて、Cを介してAからBに移動するように依頼できます。前の執事はそれを行うことができましたが、足を引きずって不平を言いました。

もう1つの幸運なことに、これを処理するために翻訳者の設定を調整できるため、言語の観点からは何も変わりません。しかし、新しい設定で古い執事と話すと、彼は混乱し、あなたが彼の言語を話していても理解できません。

はっきりしない場合は、執事は同じISAでオペレーティングシステムが異なるコンピューターです。トランスレータは、ISAを対象としたクロスコンパイラツールチェーンです。

于 2015-03-28T20:45:52.067 に答える