第6章インフラストラクチャーの抽象化層:オペレーティングシステム
Linkers and Dynamic Linkingリンカーと動的リンク
Linkers are software tools that an OS uses to combine object files into an executable file. A linker performs name resolution, matching the name of a variable or function in an application to a virtual memory address it will have when loaded and run. A linker combines many separate pieces of a program, reorganizes storage allocation so that all the pieces can fit together, and touches up addresses so that the program can run under the new memory organization. After a linker completes the task of combining multiple object files generated by a compiler into a single executable file, the executable file can be loaded and executed by the OS (Figure 6.27).
英語のヒント
リンカーは、OSがオブジェクトファイルを一つの実行可能ファイルにまとめるために使うソフトウェアの道具である。リンカーは名前解決を行い、アプリケーション内の変数や関数の名前を、読み込んで実行したときに割り当てられる仮想メモリアドレスと対応付ける。リンカーは、プログラムの多くの独立した部分を結合し、すべてを収められるよう記憶領域の割り当てを再編し、新しいメモリ構成で動くようアドレスを調整する。コンパイラーが生成した複数のオブジェクトファイルを、リンカーが一つの実行可能ファイルにまとめ終えると、OSがそのファイルを読み込み、実行できる(図6.27)。

attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license · CC BY 4.0 · Source出典
Figure 6.27 A linker process includes object files and libraries. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)
図6.27 リンカーの処理には、オブジェクトファイルとライブラリーが含まれる。(出典:著作権 Rice University、OpenStax。CC BY 4.0ライセンス)
The mechanism that allows a program to associate external code symbols to addresses at runtime is dynamic linking. The allocation process starts when the process is running by dividing the memory into smaller parts called segments. For example, Linux’s memory layout is divided such that the code starts at location 0, the data starts immediately above the code, and the stack starts at the highest address, as illustrated in Figure 6.28. When a process is started, the OS will load the file to the memory with the added option of sharing the memory with others. The OS facilitates the memory size at runtime by adding more assigned memory when needed.
英語のヒント
プログラムが、実行時に外部コードのシンボルをアドレスへ対応付けられる仕組みが、動的リンクである。割り当て処理は、プロセスの実行中に、メモリをセグメントと呼ばれる小さな部分へ分けることで始まる。たとえば図6.28のように、Linuxのメモリ配置では、コードが位置0から始まり、そのすぐ上からデータが始まり、最も高いアドレスからスタックが始まるように分割される。プロセスを開始すると、OSはファイルをメモリへ読み込む。このとき、ほかとメモリを共有する選択肢もある。OSは必要に応じて割当メモリを追加し、実行時のメモリ量に対応する。

attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license · CC BY 4.0 · Source出典
Figure 6.28 In Linux’s memory layout, the code starts at location 0, the data starts immediately above the code and grows upward, and the stack starts at the highest address and grows downward. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)
図6.28 Linuxのメモリ配置では、コードは位置0から始まる。データはコードのすぐ上から始まり、上方向に伸びる。スタックは最も高いアドレスから始まり、下方向に伸びる。(出典:著作権 Rice University、OpenStax。CC BY 4.0ライセンス)
In dynamic linking, the code is located and loaded when the program is first run. Since the late 1980s, most systems started supporting shared libraries and dynamic linking by only keeping a single copy of common library packages in memory that is shared by all processes. This means that the system does not know where the library is loaded until runtime and must resolve references dynamically when the program runs.
英語のヒント
動的リンクでは、プログラムを初めて実行するときに、コードの場所を特定して読み込む。1980年代後半以降、ほとんどのシステムは、共通のライブラリーパッケージをメモリに一つだけ保持し、すべてのプロセスで共有することで、共有ライブラリーと動的リンクをサポートするようになった。つまり、システムは実行時までライブラリーの読み込み先を知らず、プログラムの実行時に参照を動的に解決する必要がある。
Dynamic Storage Management動的記憶管理
There are two basic operations used in dynamic storage management to manage a memory or storage to satisfy various needs: allocate a block with a given number of bytes or free a previously allocated block. There are two general approaches to applying these dynamic storage allocation operations: (1) stack allocation, which is hierarchical and restricted, but simple and efficient; and (2) heap allocation, which is more general but more difficult to implement and less efficient.
英語のヒント
動的記憶管理では、さまざまな必要に応じてメモリや記憶領域を管理するために、二つの基本操作を使う。一つは、指定したバイト数のブロックを割り当てること、もう一つは、以前に割り当てたブロックを解放することである。これらの動的な記憶領域割り当て操作を使う方法には、大きく二つある。(1)スタック割り当ては、階層的で制約があるが、単純で効率がよい。(2)ヒープ割り当ては、より一般的だが、実装が難しく、効率も低い。
The linear data structure that follows a LIFO order (last in, first out), as in the stack data figure configuration in Figure 6.29, is called stack allocation. In the stack approach, the memory is freed in opposite order from allocation. For example, if procedure X calls Y, then Y will certainly return before returning from X. Stacks take advantage of this programming practice to store the state of the current procedure call. When memory allocation and freeing are partially predictable, then a stack approach can be used.
英語のヒント
図6.29のスタックの構成のように、LIFO(後入れ先出し)の順序に従う線形データ構造を、スタック割り当てという。スタック方式では、メモリを割り当てた順序と逆の順序で解放する。たとえば、手続きXがYを呼び出せば、Xから戻る前に必ずYが戻る。スタックは、このようなプログラミング上の慣行を利用して、現在の手続き呼び出しの状態を保存する。メモリの割り当てと解放がある程度予測できる場合に、スタック方式を使える。

attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license · CC BY 4.0 · Source出典
Figure 6.29 This stack data structure representation shows a last in, first out approach. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)
図6.29 このスタックのデータ構造は、後入れ先出し方式を表す。(出典:著作権 Rice University、OpenStax。CC BY 4.0ライセンス)
Allocating the data in a tree-based data structure called a heap is heap allocation. A heap is represented by a complete binary tree. As shown in Figure 6.30, a heap data structure can be of two types: max heap and min heap. Max heap presets the root node with the greatest value and the same for the sub trees. It is the opposite for the min heap, where the root will have the minimum value and the same for the sub trees.
英語のヒント
ヒープという木に基づくデータ構造へデータを割り当てることが、ヒープ割り当てである。ヒープは、完全二分木で表される。図6.30のように、ヒープのデータ構造には、最大ヒープと最小ヒープという二つの種類がある。最大ヒープでは、根のノードに最大の値を置き、部分木でも同様にする。最小ヒープでは逆で、根が最小の値を持ち、部分木でも同様になる。

attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license · CC BY 4.0 · Source出典
Figure 6.30 Heap allocation uses a data structure called a heap to manage memory and storage. There are two types of heap structures or trees: one for the max heap and one for the min heap. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)
図6.30 ヒープ割り当ては、ヒープというデータ構造を使って、メモリと記憶領域を管理する。ヒープの構造、つまり木には、最大ヒープ用と最小ヒープ用の二種類がある。(出典:著作権 Rice University、OpenStax。CC BY 4.0ライセンス)
Memory managers, such as the ones used in C and C++, do not actually store available memory in a heap data structure. Instead, they manipulate a doubly linked list of blocks, which they confusingly refer to as a “heap,” and attempt to optimize memory using a “best fit” method.
英語のヒント
CやC++で使われるものなど、メモリ管理機構は、実際には、利用可能なメモリをヒープのデータ構造に保存するわけではない。代わりに、ブロックの双方向連結リストを操作し、それを紛らわしくも「ヒープ」と呼んで、「ベストフィット」という方法でメモリの最適化を図る。
Memory managers use the heap approach when the allocation and release of memory are not predictable (i.e., when it is not clear how much memory is needed until we run the program). Typically, the heap stores data structures that can change in size over time based on how many elements are added or removed from the data structure. The corresponding heap memory consists of allocated areas and free areas (or holes).
英語のヒント
メモリ管理機構は、メモリの割り当てと解放を予測できない場合、つまり、プログラムを動かすまで必要量が分からない場合に、ヒープ方式を使う。一般に、ヒープには、追加または削除される要素数に応じて、時間とともに大きさが変わるデータ構造を格納する。対応するヒープメモリは、割り当て済みの領域と、空き領域(ホール)から構成される。