2012-03-20 21 views
1

私は、カーネルが仮想メモリを実メモリにマッピングすることを知っています。しかし、私は実際に/ proc/pid/mapsファイルに示されているようにプロセスの仮想メモリを誰が作成するのか知りたい。Linuxに仮想メモリを作成するのは誰ですか?

1)プロセス用の仮想メモリ領域を作成するのはコンパイラ/リンカですか(カーネルは実際のメモリにマッピングするだけです(仮想メモリ領域は問題ではなく、すべてのマッピングにとって重要です)。

2)または、プロセスをフォークする際にカーネル自身が仮想メモリ空​​間を作成し、それを実メモリにマップしますか?

最後に、mmapシステムコール(1)または(2)は何をしますか?

答えて

1

カーネルは、実際にを作成し、あなたは/ procの/ PID /マップに表示さ仮想メモリ領域を管理するエンティティです。各プロセスの状態を保持する構造体(struct task_struct)には、struct mm_struct(linux/sched.hの中にあります)があり、特にその中にはstruct vm_area_struct * mmapがあります。これはプロセスアドレス空間にマップされたすべてのメモリ領域(領域記述子と呼ばれる)のカーネルによって維持されるリストである。 mmapが呼び出されると、このリストに新しい要素が追加され、その後に/ proc/pid/mapsに表示されます。

ファイルにバックアップされた領域のほとんどは、/proc/pid/mapsにリストされているlibc.soは、プロセスの起動時に動的リンカ(ld.so)のコードによってマッピングされます。

カーネルは、絶対に必要となるまで、これらの領域にあるアドレスの仮想物理マッピングを作成しません。

希望します。

3

両方のアサーションは実際には正しい(ある程度までは)。

実行可能なELFファイルの場合、リンカはリンカスクリプトを使用して仮想空間内のアドレスをプログラムのすべてのシンボルに割り当てます(これらはすべて開始アドレスとサイズを持つセクションにグループ化されています)。 ld --verboseを呼び出すことによって使用される既定のスクリプトが表示されます。バイナリのセクションとそのアドレスはreadelfまたはobjdumpなどのツールを使用して表示できます。 readelf -l /bin/cat。次にcat /proc/self/mapsを実行する場合は、/bin/catがマップされているアドレスが一致する必要があります。したがって、execveカーネルシステムコールは、現在のプロセスのアドレス空間を、引数として与えられた実行可能ファイルがマップされている新しいものに置き換えます。

もちろん、コードのすべてのビットに静的アドレスが割り当てられていれば、共有ライブラリの問題を解決できます。共有ライブラリは位置に依存しないコードを使用するため、プロセスアドレス空間のどこにでもマップすることができます。ここで、カーネルはどのように進めるかについて決定を下します。

mmap(1)または(2)のいずれも、アドレス空間の所定のアドレスにメモリまたはファイルの一部をマップしません(またはカーネルに使用するアドレスを決定させる)。実際には、プログラムが使用する共有ライブラリをマップするために使用されます。方法を見るには、strace /bin/trueを実行し、最初にexecveが呼び出され、プロセスのアドレス空間がバイナリファイルから作成され、libcファイルがどのように開かれ、適切なセクションが適切な権限でmmapされているかを確認してください。

execve("/bin/true", ["/bin/true"], [/* 69 vars */]) = 0 
... 
open("/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
mmap(NULL, 3804080, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f224f351000 
mprotect(0x7f224f4e8000, 2097152, PROT_NONE) = 0 
mmap(0x7f224f6e8000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x197000) = 0x7f224f6e8000 

以下の記事も読んで価値があるかもしれない:

関連する問題