<!--Chapter 4 Processes-->
<sect>プロセス<label id="chapter_p">
<p>
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/penguin2.gif">
</figure>

<!--
This chapter describes what a process is and how the Linux kernel creates,
manages and deletes the processes in the system. 
-->
<p>この章ではプロセスとは何かを説明し、Linux がシステム上でプロセスをどの
ように生成、管理、削除しているのかについて解説する。

<!--
Processes carry out tasks within the operating system. A program is a set of
machine code instructions and data stored in an executable image on disk and 
is, as such, a passive entity; a process can be thought of as a computer 
program in action. 
It is a dynamic entity, constantly changing as the machine code instructions 
are executed by the processor. As well as the program's instructions and data,
the process also includes the program counter and all of the CPU's registers 
as well as the process stacks containing temporary data such as routine 
parameters, return addresses and saved variables. The current executing 
program, or process, includes all of the current activity in the 
microprocessor. Linux is a multiprocessing operating system. Processes are 
separate tasks each with their own rights and responsibilities. If one process
crashes it will not cause another process in the system to crash. Each 
individual process runs in its own virtual address space and is not capable of
interacting with another process except through secure, kernel managed 
mechanisms. 
-->
<p>プロセスはオペレーティングシステム内でタスクを実行する。プログラムと
は、実行イメージとしてディスクに保存されたマシン語の命令とデータとのセットで
ある。したがって、プログラムとは受動的な実体である。反対に、
プロセスとは実行中のコンピュータプログラムであると考えることができる。
プロセスはダイナミックな実体であり、マシン語の命令がプロセッサにより実行される
につれて常に変化してゆく。プログラムという概念が命令とデータを含むものである
ように、プロセスも、プログラムカウンタ(program counter)など CPU の全レジスタ
情報やプロセススタックを含む概念であり、それらが保持する一時データであるルー
チンパラメータや戻りアドレス、保存された変数などを包含する概念である。
現在実行中のプログラムもしくはカレントプロセス(current process)とは、マイクロプ
ロセッサでの現在の活動すべてを含む概念である。
<p>
Linux はマルチプロセスのオペレーティングシステムである。プロセスとは
個別のタスクであり、それぞれが独自の権限と責任を持つ。ひとつのプロセスが
クラッシュした場合でも、それが他のプロセスをクラッシュさせることはない。
個々の独立したプロセスが独自の仮想アドレス空間で実行されていて、カーネルが
管理する安全な仕組みを使う場合を除いては、他のプロセスと相互に影響を与えあう
ことはない。

<!--
During the lifetime of a process it will use many system resources. It will 
use the CPUs in the system to run its instructions and the system's physical 
memory to hold it and its data. It will open and use files within the 
filesystems and may directly or indirectly use the physical devices in the 
system. Linux must keep track of the process itself and of the system 
resources that it has so that it can manage it and the other processes in the 
system fairly. It would not be fair to the other processes in the system if 
one process monopolized most of the system's physical memory or its CPUs. 
-->
<p>プロセスは、そのライフサイクルの中で、多くのシステムリソース(system 
resources)を使用する。命令を実行するときにはシステムの CPU を使用し、自分自身
とそのデータを保持するにはシステムの物理メモリを使用する。ファイルシステム内
でファイルをオープンして使用し、システムの物理デバイスを直接・間接に利用する
場合もある。Linux は、プロセス自体とそれが持つシステムリソースを常に
監視することで、システム内の当該プロセスとその他のプロセスを公平に管理しなけ
ればならない。ひとつのプロセスがシステムの物理メモリや CPU を独占したとしたら、
それはシステムの他のプロセスに対して公平とは言えない。

<!--
The most precious resource in the system is the CPU, usually there is only one.
Linux is a multiprocessing operating system, its objective is to have a process
running on each CPU in the system at all times, to maximize CPU utilization. If
there are more processes than CPUs (and there usually are), the rest of the
processes must wait before a CPU becomes free until they can be run.
Multiprocessing is a simple idea; a process is executed until it must wait, 
usually for some system resource; when it has this resource, it may run again.
In a uniprocessing system, for example DOS, the CPU would simply sit idle and 
the waiting time would be wasted. In a multiprocessing system many processes 
are kept in memory at the same time. Whenever a process has to wait the 
operating system takes the CPU away from that process and gives it to another,
more deserving process. It is the scheduler which chooses which is the most
appropriate process to run next and Linux uses a number of scheduling 
strategies to ensure fairness. 
-->
<p>システムの最も貴重なリソースは、CPU である。それは通常ひとつしかない。
Linux はマルチプロセス(multiprocessing)のオペレーティングシステムであり、
その目標は、ひとつのプロセスをシステムの個別の CPU 上で常時走らせて、CPU の
使用効率を最大限に上げることである。
もしプロセスの数が CPU の数を上回る場合(通常はそうである)、残りのプロセスは、
プロセスの実行が終わって CPU が空くまで待たなければならない。
マルチプロセッシングのアイデアは単純である。プロセスが実行されると、通常何らか
のシステムリソースのために待ち状態となり、リソースが得られると実行を再開する。
DOS のような単一プロセス(uniprocessing)のシステムでは、CPU はその間、単に待って
いるだけで、待ち時間は無駄になる。マルチプロセッシングシステムでは、多くの
プロセスが同時にメモリに保持されている。プロセスに待ち時間が生じたとき、
オペレーティングシステムはそのプロセスから CPU を取り上げて、より優先すべき
他のプロセスにそれを与える。次に実行するプロセスとしてどれが最も適切かを決定
するのがスケジューラ(scheduler)であり、Linux は、公平を期すためにいくつかの
スケジューリングの戦略を使っている。

<!--
Linux supports a number of different executable file formats, ELF is one, Java
is another and these must be managed transparently as must the processes use of
the system's shared libraries. 
-->
<p>Linux は、多くの実行ファイルフォーマットをサポートしている。ELF はその
ひとつであり、Java もそうである。プロセスがシステムの共有ライブラリを透過的
に扱えるようにしなければならないのと同様に、それらのファイルフォーマットも
透過的に扱われるよう管理されなければならない。

<!--4.1  Linux Processes-->
<sect1>Linux のプロセス<label id="chapter_p_sect1">

<!--
So that Linux can manage the processes in the system, each process is
represented by a task_struct data structure (task and process are terms that
Linux uses interchangeably). The task vector is an array of pointers to every
task_struct data structure in the system. This means that the maximum number 
of processes in the system is limited by the size of the task vector; by 
default it has 512 entries. As processes are created, a new task_struct is 
allocated from system memory and added into the task vector. To make it easy 
to find, the current, running, process is pointed to by the current pointer. 
-->
<p>Linux がシステム上のプロセスを管理できるようにするため、個々のプロセスは、
<tt><ref id="task_struct" name="task_struct"></tt> というデータ構造体で表現さ
れる。(task と process という用語は、Linux では同義として使われている。) 
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/linux/sched.h"
name="include/linux/sched.h">]<newline>
その <tt><ref id="task" name="task"></tt> 配列は、システム上の
すべての <tt>task_struct</tt> データ構造に対するポインタの配列である。このこと
が意味するのは、システム上のプロセスの最大数がその <tt>task</tt> 配列のサイズに
よって制限されるということである。デフォルトでは、それは 512 のエントリを持つ。
プロセスが生成されると、新しい <tt>task_struct</tt> がシステムメモリに
割り当てられ、<tt>task</tt> 配列に追加される。発見を容易にするために、
現在実行中のプロセスは、<tt><ref id="task" name="current"></tt> ポインタ
によってポイントされている。


<!--
As well as the normal type of process, Linux supports real time processes. 
These processes have to react very quickly to external events (hence the 
term ``real time'') and they are treated differently from normal user 
processes by the scheduler. Although the task_struct data structure is quite 
large and complex, but its fields can be divided into a number of functional 
areas: 
-->
<p>通常タイプのプロセスだけでなく、Linux ではリアルタイムプロセス(real time 
process)もサポートしている。そうしたプロセスは外界イベントに即座に反応しなけ
ればならない(したがって、「リアルタイム」という用語が使われる)ので、
スケジューラからは通常のユーザプロセスとは異なる扱いを受ける。
<tt><ref id="task_struct" name="task_struct"></tt> のデータ構造体は極めて巨大
で複雑だが、そのフィールドはいくつかの機能別エリアに分けることができる。

<!--
State As a process executes it changes state according to its circumstances.
      Linux processes have the following states: 1 
      Running
            The process is either running (it is the current process in the
            system) or it is ready to run (it is waiting to be assigned to one
            of the system's CPUs). 
      Waiting
            The process is waiting for an event or for a resource. Linux
            differentiates between two types of waiting process; interruptible
            and uninterruptible. Interruptible waiting processes can be
            interrupted by signals whereas uninterruptible waiting processes
            are waiting directly on hardware conditions and cannot be
            interrupted under any circumstances. 
      Stopped
            The process has been stopped, usually by receiving a signal. A
            process that is being debugged can be in a stopped state. 
      Zombie
            This is a halted process which, for some reason, still has a
            task_struct data structure in the task vector. It is what it
            sounds like, a dead process. 
-->
<descrip>
<tag>状態(State)</tag>
プロセスは、実行中に、環境に応じて状態を変化させる。Linux のプロセスは次のよ
うな状態(state)を取る。(<ref id="chapter_p_fn1" name="脚注1">)
<descrip>

<p><tag>実行中(Running)</tag>
この状態のプロセスは、走行中(システム上で現在走行中のプロセス)か、直ぐに走行
できる(システム上の CPU の割り当てを待っている状態)かのいずれかである。

<p><tag>待機中(Waiting)</tag>
この状態のプロセスは、イベントかリソースを待っている状態である。Linux は、
待機状態のプロセスを割り込み可能(interruptible)か割り込み不可
(uninterruptible)かどうかで区別する。割り込み可能な待機中の
プロセスとはシグナルによって割り込みを掛け得るものであり、割り込み不可な待機
中のプロセスとは、直接ハードウェアの状態に依存するかたちで待機しているので、
どのような状況でも割り込みを掛けられないものをいう。

<p><tag>停止中(Stopped)</tag>
この状態のプロセスは、通常はシグナルを受信したことで停止状態にある。デバッグ
中のプロセスは、停止状態に置くことが可能である。

<p><tag>ゾンビ(Zombie)</tag>
これは終了したプロセスだが、何らかの理由で、<tt><ref id="task" name="task">
</tt> 配列内に <tt><ref id="task_struct" name="task_struct"></tt> 構造体を
まだ持っているものである。これは、その名の通り、既に死んでいるプロセスである。
</descrip>

<!--
Scheduling Information
      The scheduler needs this information in order to fairly decide which
      process in the system most deserves to run, 
-->
<tag>スケジューリング情報(Scheduling Information)</tag>
スケジューラ(scheduler)は、どのプロセスをシステム内で最も優先的に実行すべきか
公平に判断するために、この情報を必要とする。

<!--
Identifiers
      Every process in the system has a process identifier. The process
      identifier is not an index into the task vector, it is simply a number. 
      Each process also has User and group identifiers, these are used to 
      control this processes access to the files and devices in the system, 
-->
<tag>識別子(Identifiers)</tag>
システム内のすべてのプロセスはプロセス識別子を持つ。プロセス識別子は、<tt>task
</tt> 配列へのインデックスではなく、単なる番号である。また個々のプロセスは
ユーザ ID およびグループ ID も持ち、それらの識別子はシステムのファイルやデバイ
スに対するこのプロセスのアクセス制御のために使用される。

<!--
Inter-Process Communication
      Linux supports the classic Unix TM IPC mechanisms of signals, pipes and
      semaphores and also the System V IPC mechanisms of shared memory,
      semaphores and message queues. The IPC mechanisms supported by
      Linux are described in Chapter  IPC-chapter. 
-->
<tag>プロセス間通信(Inter-Process Communication, IPC)</tag>
Linux は、シグナル、パイプ、セマフォという古典的な Unix IPC メカニズムを
サポートすると同時に、共有メモリ、セマフォ、メッセージキューといった System V 
IPC メカニズムもサポートしている。Linux でサポートされている IPC のメカニズム
については、<ref id="chapter_ipc" name="「プロセス間通信の仕組み」">の章で
解説する。

<!--
Links In a Linux system no process is independent of any other process. Every
      process in the system, except the initial process has a parent process.
      New processes are not created, they are copied, or rather cloned from
      previous processes. Every task_struct representing a process keeps
      pointers to its parent process and to its siblings (those processes with
      the same parent process) as well as to its own child processes. You can 
      see the family relationship between the running processes in a Linux 
      system using the pstree command: 
-->
<tag>リンク(Links)</tag>
Linux システムでは、他のプロセスから完全に独立したプロセスは存在しない。シス
テム上のすべてのプロセスは、初期化プロセスを除いて、親プロセス(parent 
process)を持つ。新しいプロセスは創造されるのではなく、コピーされるのであり、
むしろ以前のプロセスのクローンとして生まれるのである。プロセスを表現する <tt>
<ref id="task_struct" name="task_struct"></tt> 構造体はすべて、自分の子プロセス
(child process)へのポインタを保持すると同時に、その親プロセスと兄弟プロセス
(siblings)(同じ親プロセスを持つプロセス)へのポインタを保持している。
<tt>pstree</tt> コマンドを使えば、Linux システム上で実行中のプロセス間の家族
関係を見ることができる。

<verb>
init(1)-+-crond(98)
        |-emacs(387)
        |-gpm(146)
        |-inetd(110)
        |-kerneld(18)
        |-kflushd(2)
        |-klogd(87)
        |-kswapd(3)
        |-login(160)---bash(192)---emacs(225)
        |-lpd(121)
        |-mingetty(161)
        |-mingetty(162)
        |-mingetty(163)
        |-mingetty(164)
        |-login(403)---bash(404)---pstree(594)
        |-sendmail(134)
        |-syslogd(78)
        `-update(166)
</verb>
<!--
      Additionally all of the processes in the system are held in a doubly 
      linked list whose root is the init processes task_struct data structure.
      This list allows the Linux kernel to look at every process in the 
      system. It needs to do this to provide support for commands such as ps 
      or kill. 
-->
さらに、システム内のあらゆるプロセスは、二重連結リストの中に保持されていて、
そのリストのルートは、<tt>init</tt> プロセスの <tt>task_struct</tt> 構造体
となっている。このリストがあることで、Linux カーネルはシステム上のすべての
プロセスを見ることができる。<tt>ps</tt> や <tt>kill</tt> といったコマンドを
サポートするために、カーネルにはこの機能が必要である。

<!--Times and Timers-->
<tag>時間とタイマー</tag>
<!--
      The kernel keeps track of a processes creation time as well as the CPU
      time that it consumes during its lifetime. Each clock tick, the kernel
      updates the amount of time in jiffies that the current process has spent
      in system and in user mode. Linux also supports process specific interval
      timers, processes can use system calls to set up timers to send signals 
      to themselves when the timers expire. These timers can be single-shot or
      periodic timers. 
-->
<p>カーネルは、プロセスが生成された時間と、プロセスの生存時間内での CPU 使用
時間とを監視している。クロックティック(<ref id="clock_tick" name="clock tick">)
ごとに、カーネルは、走行中のプロセスのシステムモードおよびユーザモードでの経過
時間を変数 <tt><ref id="task" name="jiffies"></tt> 
の値を使って更新する。また、Linux は
プロセス固有のインターバルタイマー(interval timer)もサポートしているので、
プロセスはシステムコールを利用してタイマーをセットし、所定時間が経過すると
自分自身にシグナルを送るように設定することもできる。そうしたタイマーは、
一回だけ使うことも定期的に使用することもできる。

<!--File system-->
<tag>ファイルシステム (File system)</tag>
<!--
      Processes can open and close files as they wish and the processes
      task_struct contains pointers to descriptors for each open file as well
      as pointers to two VFS inodes. Each VFS inode uniquely describes a file
      or directory within a file system and also provides a uniform interface 
      to the underlying file systems. How file systems are supported under 
      Linux is described in Chapter  filesystem-chapter. The first is to the 
      root of the process (its home directory) and the second is to its 
      current or pwd directory. pwd is derived from the Unix TM command pwd, 
      print working directory. These two VFS inodes have their count fields 
      incremented to show that one or more processes are referencing them. 
      This is why you cannot delete the directory that a process has as its 
      pwd directory set to, or for that matter one of its sub-directories. 
-->
<p>プロセスは、好きなときにファイルのオープンやクローズができる。プロセスの 
<tt><ref id="task_struct" name="task_struct"></tt> 構造体には、オープンされた
それぞれのファイルのディスクリプタに対するポインタと、ふたつの VFS inode に対
するポインタが含まれている。
個々の VFS inode はファイルシステム内のファイルかディレクトリをユニークに記述
するもので、基盤となるファイルシステムに対する統一的なインターフェイスを提供
するものである。
Linux 上でファイルシステムがどのようにサポートされているかは、
<ref id="chapter_fs" name="「ファイルシステム」">の章で述べられている。
最初の VFS inode はプロセスのルート(そのホームディレクト
リ)に対するものであり、二番目の VFS inode はカレント(もしくは pwd )
ディレクトリに対するもの
である。ここで pwd という呼び方は、Unix のコマンド <tt>pwd</tt> (print working 
directory)に由来するものである。これらふたつの VFS inode は、それぞれの <tt>
<ref id="inode" name="count"></tt>フィールドを増加させて、ひとつ以上のプロセ
スがそのディレクトリを参照中であることを示す。それゆえ、あるプロセスが pwd 
ディレクトリとしてセットしているディレクトリは削除できず、同様にそのサブディ
レクトリも削除できないということが起こる。

<!--Virtual memory-->
<tag>仮想メモリ (Virtual memory)</tag>
<!--
      Most processes have some virtual memory (kernel threads and daemons
      do not) and the Linux kernel must track how that virtual memory is mapped
      onto the system's physical memory. 
-->
<p>大部分のプロセスは、何らかの仮想メモリを持っている。(カーネルスレッド
(kernel threads)とデーモン(daemons)はそうではない。) そして、Linux カーネル
は、そうした仮想メモリがどのようにシステムの物理メモリにマップされているのか
を常に監視しなければならない。

<!--Processor Specific Context--><label id="chapter_p_context">
<tag>プロセッサ固有のコンテキスト (Processor Specific Context)</tag>
<!--
      A process could be thought of as the sum total of the system's current
      state. Whenever a process is running it is using the processor's 
      registers, stacks and so on. This is the processes context and, when a 
      process is suspended, all of that CPU specific context must be saved in 
      the task_struct for the process. When a process is restarted by the
      scheduler its context is restored from here. 
-->
<p>プロセスとは、現在のシステム状態(system state)の総体であると考えることがで
きる。プロセスの走行中には、プロセッサのレジスタやスタック等が使用されている。
これはプロセスのコンテキスト(context)であり、プロセスがサスペンドされたときに
は、その CPU 固有の全コンテキストが、 プロセスの <tt><ref id="task_struct" 
name="task_struct"></tt> 構造体に保存される。プロセスがスケジューラにより再
始動されたときは、そのコンテキストが <tt>task_struct</tt> データ構造体から
回復される。
</descrip>

<!--4.2  Identifiers-->
<sect1>識別子(identifiers)<label id="chapter_p_sect2">

<!--
Linux, like all Unix TM uses user and group identifiers to check for access 
rights to files and images in the system. All of the files in a Linux system 
have ownerships and permissions, these permissions describe what access the 
system's users have to that file or directory. Basic permissions are read, 
write and execute and are assigned to three classes of user; the owner of the 
file, processes belonging to a particular group and all of the processes in 
the system. Each class of user can have different permissions, for example a 
file could have permissions which allow its owner to read and write it, the 
file's group to read it and for all other processes in the system to have no 
access at all. 
-->
<p>Linux は、他のすべての Unix と同様に、ユーザ ID とグループ ID を使用して
システム上のファイルやイメージへのアクセス権をチェックする。Linux システム上の
すべてのファイルは、所有者とパーミッションとを持っていて、そのパーミッション
によってシステム上のユーザが該当するファイルやディレクトリに対してどのような
アクセス権を持つのかを記述している。基本的なパーミッションには、読み出し
(read)、書き込み(write)、実行(execute)があり、それらがユーザの 3 つのクラス、
すなわちファイル所有者、特定のグループの属するプロセス、およびシステム上のす
べてのプロセスというクラスごとに割り当てられている。それぞれのユーザのクラスが
異なるパーミッションを持つということが可能である。たとえば、所有者には書き込み
と読み出しが可能なファイルでも、そのファイルのグループには読み出しのみが可能
であり、システム上の他のすべてのプロセスではまったくアクセスできないという
設定が可能である。

<!--
REVIEW NOTE: Expand and give the bit assignments (777). 
-->
REVIEW NOTE: この部分を詳しくして、ビット割り当てについて説明すること。(777)


<!--
Groups are Linux's way of assigning privileges to files and directories for a 
group of users rather than to a single user or to all processes in the system.
You might, for example, create a group for all of the users in a software 
project and arrange it so that only they could read and write the source code 
for the project. A process can belong to several groups (a maximum of 32 is 
the default) and these are held in the groups vector in the task_struct for 
each process. So long as a file has access rights for one of the groups that 
a process belongs to then that process will have appropriate group access 
rights to that file. 
-->
<p>個人ユーザやシステム上のすべてのプロセスに対して、ファイルやディレクトリへ
のアクセス権権を与えるのではなく、ユーザグループ単位でそれらの権限を割り当て
るのが Linux の流儀である。たとえば、あるソフトウェアプロジェクトに参加した
ユーザ全員のグループを作成し、そのプロジェクトのソースコードに対してその
グループだけが読み書きできるように権限を割り当てることができる。ひとつの
プロセスが複数のグループに属することも可能であり(デフォルトで最大 32 グループ
)、それらの情報は、プロセスごとの <tt><ref id="task_struct" name="task_struct">
</tt> 構造体の <tt>groups</tt> 配列に保持される。あるプロセスが複数のグループ
に属していて、そのうちひとつのグループがファイルへのアクセス権をもっている
場合、そのプロセスは当該ファイルへの適切なグループアクセス権を持つことになる。

<!--
There are four pairs of process and group identifiers held in a processes
task_struct: 
-->
<p>プロセスの <tt><ref id="task_struct" name="task_struct"></tt> 構造体には、
プロセスとグループの識別子に関する 4 組の情報がある。

<descrip>
<!--
uid, gid The user identifier and group identifier of the user that the 
         process is running on behalf of, 
-->
<tag><tt>uid と gid</tt></tag>
実行中のプロセスを代表するユーザ識別子(User ID)とグループ識別子(Group ID)。

<!--
effective uid and gid
      There are some programs which change the uid and gid from that of the
      executing process into their own (held as attributes in the VFS inode
      describing the executable image). These programs are known as setuid
      programs and they are useful because it is a way of restricting accesses
      to services, particularly those that run on behalf of someone else, for
      example a network daemon. The effective uid and gid are those from the
      setuid program and the uid and gid remain as they were. The kernel checks
      the effective uid and gid whenever it checks for privilege rights. 
-->
<tag><tt>実効(effective) uid と gid</tt></tag>
プログラムのなかには、実行プロセスの <tt>uid</tt> と <tt>gid</tt> をプログラム
自体の <tt>uid</tt> と <tt>gid</tt> に変更するものがある。(実行イメージ自体の 
<tt>uid</tt> と <tt>gid</tt> は、VFS inode の属性値として保持されている。)
そうしたプログラムは、<tt>setuid</tt> プログラムと呼ばれていて、アクセス制限、
特に個別のユーザを持たずに実行されるネットワークデーモンのようなサービスへの
アクセスを制限するひとつの方法として有益なものである。
実効 <tt>uid</tt> と <tt>gid</tt> とは、<tt>setuid</tt> プログラムの <tt>
uid</tt> と <tt>gid</tt> が使用され、実(real) <tt>uid</tt> と <tt>gid</tt> も
元のまま残される。カーネルが権限のチェックをする
ときはいつも、実効 <tt>uid</tt> と <tt>gid</tt> をチェックする。

<!--
file system uid and gid
      These are normally the same as the effective uid and gid and are used
      when checking file system access rights. They are needed for NFS
      mounted filesystems where the user mode NFS server needs to access
      files as if it were a particular process. In this case only the file 
      system uid and gid are changed (not the effective uid and gid). This 
      avoids a situation where malicious users could send a kill signal to 
      the NFS server. Kill signals are delivered to processes with a 
      particular effective uid and gid. 
-->
<tag><tt>ファイルシステムの uid と gid</tt></tag>
これらは通常、実効 <tt>uid</tt> や <tt>gid</tt> と同じであり、ファイルシステム
へのアクセス権限をチェックする際に使用される。これらは、NFS でマウントされた
ファイルシステムにとって必要なものである。ユーザモードの NFS サーバは、あたかも
それ自身がある特定のプロセスであるかのようにファイルにアクセスする必要があるか
らである。
その場合、(実効 <tt>uid</tt> と <tt>gid</tt> ではなく)ファイルシステムの 
<tt>uid</tt> と <tt>gid</tt> だけが変更される。これは、悪意のあるユーザが NFS 
サーバに <tt>kill</tt> シグナルを送ることができるという状態を避けるためである。
それゆえ、<tt>kill</tt> シグナルは、特定の実効 <tt>uid</tt> および <tt>gid</tt> 
を持つプロセスに配信される。

<!--
saved uid and gid
      These are mandated by the POSIX standard and are used by programs
      which change the processes uid and gid via system calls. They are used to
      save the real uid and gid during the time that the original uid and gid 
      have been changed. 
-->
<tag><tt>保存された uid と gid</tt></tag>
これらは、POSIX 規格で義務付けられており、システムコール経由でプロセスの <tt>
uid</tt> と <tt>gid</tt> を変更するプログラムによって利用される。それらは、実 
<tt>uid</tt> と <tt>gid</tt> が変更されている間、そのオリジナルな <tt>uid</tt> 
と <tt>gid</tt> を保存するために使用される。
</descrip>

<!--4.3  Scheduling-->
<sect1>スケジューリング<label id="chapter_p_sect3">

<!--
All processes run partially in user mode and partially in system mode. How 
these modes are supported by the underlying hardware differs but generally 
there is a secure mechanism for getting from user mode into system mode and 
back again. User mode has far less privileges than system mode. Each time a 
process makes a system call it swaps from user mode to system mode and 
continues executing. At this point the kernel is executing on behalf of the 
process. In Linux, processes do not preempt the current, running process, they
cannot stop it from running so that they can run. Each process decides to 
relinquish the CPU that it is running on when it has to wait for some system 
event. For example, a process may have to wait for a character to be read from
a file. This waiting happens within the system call, in system mode; the 
process used a library function to open and read the file and it, in turn made
system calls to read bytes from the open file. In this case the waiting 
process will be suspended and another, more deserving process will be chosen 
to run. 
-->
<p>すべてのプロセスは、ある時はユーザモードで、ある時はシステムモードで走行
する。基礎になるハードウェアがそれらのモードをサポートする方法はハードウェア
によって異なるが、一般的には、ユーザモードからシステムモードへの移行および
その逆に移行する場合の安全なメカニズムというものが存在する。ユーザモードは
システムモードよりもずっと限られた特権しか持たない。プロセスはシステムコール
を実行するたびに、ユーザモードからシステムモードに移行して実行を継続する。
このとき、カーネルはそのプロセスを代表して実行を行う。
Linux では、プロセスは、現在走行
中のプロセスを横取り(preempt)しない。自分が実行されるために走行中のプロセスを
止めることはできない。プロセスは、自分が何らかのシステムイベントを待たなけれ
ばならないとき、使用中の CPU を放棄するかどうかを決める。たとえば、あるプロセス
は、ファイルから一文字読み出されるまで待たなければならないかもしれない。
この待機状態は、システムモードにおけるシステムコールによって起こる。
すなわち、プロセスは、ファイルの open や read のためにライブラリ関数を使用し、
次にそのライブラリ関数がシステムコールを発して open されたファイルから
バイト列を read する。この場合、待機中のプロセスはサスペンドされ、その間に
他のより優先度の高いプロセスが選ばれて実行される。

<!--
Processes are always making system calls and so may often need to wait. Even
so, if a process executes until it waits then it still might use a 
disproportionate amount of CPU time and so Linux uses pre-emptive scheduling. 
In this scheme, each process is allowed to run for a small amount of time, 
200ms, and, when this time has expired another process is selected to run and 
the original process is made to wait for a little while until it can run 
again. This small amount of time is known as a time-slice. 
-->
<p>プロセスは終始システムコールを実行するので、しばしば待機する必要が生じる。
その場合でも、もしプロセスが待機状態になるまで実行され続けるとすると、その
プロセスはやはり不公平な CPU 時間を消費していることになり、したがって Linux は
横取り可能(pre-emptive)なスケジューリングを使わざるを得なくなるだろう。
実際の仕組みでは、個々のプロセスは 200ms の短い時間走行を許され、その時間が経過
すると次のプロセスが選ばれて実行され、もとのプロセスは再度実行が可能になるまで
しばらく待たされる。この短い時間間隔は、タイムスライス(time-slice)と呼ばれる。

<!--
It is the scheduler that must select the most deserving process to run out of 
all of the runnable processes in the system. 
A runnable process is one which is waiting only for a CPU to run on. Linux 
uses a reasonably simple priority based scheduling algorithm to choose between
the current processes in the system. When it has chosen a new process to run it
saves the state of the current process, the processor specific registers and 
other context being saved in the processes task_struct data structure. It then
restores the state of the new process (again this is processor specific) to 
run and gives control of the system to that process. For the scheduler to 
fairly allocate CPU time between the runnable processes in the system it keeps
information in the task_struct for each process: 
-->
<p>システム上の実行可能なすべてのプロセスの中から最も優先するプロセスを選んで
実行させる役割を担うのがスケジューラ(scheduler)である。
<newline>[see: shedule(), in 
<htmlurl url="The-Linux-Kernel-images/linux/kernel/sched.c"
name="kernel/sched.c">]<newline>
実行可能なプロセスとは、CPU が空きさえすれば直ぐに走行可能なプロセスである。
Linux は、優先度(priority)ベースの適度にシンプルなスケジューリングアルゴリズ
ムを使ってシステム上の走行プロセスを選択している。新しいプロセスを選んで実行
するとき、Linux は、まず現在実行中のプロセスの状態(state)、すなわちプロセッサ
固有のレジスタ内容、およびプロセスの 
<tt><ref id="task_struct" name="task_struct"></tt> データ構造体に保持さ
れたその他のコンテキストを保存する。そして、新しいプロセスの状態(これもプロ
セッサ固有のものである)を復元して実行し、システムの制御をそのプロセスに渡す。
スケジューラがシステム上の実行可能なプロセスに対して公平に CPU 時間を割り当てる
ために、Linux は個々のプロセスの <tt>task_struct</tt> 構造体内の情報を保持して
いる。その情報とは次のようなものである。

<descrip>
<!--
policy This is the scheduling policy that will be applied to this process. 
      There are two types of Linux process, normal and real time. Real time 
      processes have a higher priority than all of the other processes. If 
      there is a real time process ready to run, it will always run first. 
      Real time processes may have two types of policy, round robin and first 
      in first out. In round robin scheduling, each runnable real time process
      is run in turn and in first in, first out scheduling each runnable 
      process is run in the order that it is in on the run queue and that 
      order is never changed. 
-->
<tag><tt>ポリシー (policy)</tt></tag>
これは、該当プロセスに適用されるスケジューリングポリシーである。Linux のプロ
セスには、ノーマルとリアルタイムのふたつのタイプがある。リアルタイムプロセス
は、他のどのプロセスよりも高い優先度を持つ。実行可能なリアルタイムプロセスが
ある場合、まずそれが常に実行される。リアルタイムプロセスは、ラウンドロビン
(round robin)と先入れ先出し(first in first out)というふたつのタイプのポリシー
を持ち得る。ラウンドロビンスケジューリングでは、個々の実行可能なリアルタイム
プロセスは順番に実行されるが、先入れ先出しスケジューリングでは、個々のプロセ
スは実行キューに置かれた順序で実行され、その順番は絶対に変更されない。

<!--
priority This is the priority that the scheduler will give to this process. It
      is also the amount of time (in jiffies) that this process will run for 
      when it is allowed to run. You can alter the priority of a process by 
      means of system calls and the renice command. 
-->
<tag><tt>優先度 (priority)</tt></tag>
これは、該当するプロセスに対してスケジューラが与える優先度である。これは、
実行を許された時に、そのプロセスが走行可能な
(<tt><ref id="clock_tick" name="jiffies"></tt> 値で表された)時間間隔でもあ
る。システムコールや <tt>renice</tt> コマンドを使用すれば、プロセスの優先度
を変更することができる。

<!--
rt_priority
      Linux supports real time processes and these are scheduled to have a
      higher priority than all of the other non-real time processes in system.
      This field allows the scheduler to give each real time process a relative
      priority. The priority of a real time processes can be altered using 
      system calls. 
-->
<tag><tt>リアルタイムプロセスの優先順位 (rt_priority)</tt></tag>
Linux はリアルタイムプロセスをサポートしており、それらはシステム上の他のどの非
リアルタイムプロセスよりも高い優先順位でスケジューリングされる。このフィールド
は、スケジューラによる個々のリアルタイムプロセスに対する相対的な優先順位の付与
を可能にするものである。リアルタイムプロセスの優先順位は、システムコールを
使用すれば変更できる。

<!--
counter
      This is the amount of time (in jiffies) that this process is allowed to
      run for. It is set to priority when the process is first run and is
      decremented each clock tick. 
-->
<tag><tt>カウンタ (counter)</tt></tag>
これは、当該プロセスが実行を許可される
(<tt><ref id="clock_tick" name="jiffies"></tt> 値で表された)時間間隔である。
これはプロセスが初めて実行される時に <tt>priority</tt> に対して設定され、
クロックティックごとに減少していく。

</descrip>

<!--
The scheduler is run from several places within the kernel. It is run after 
putting the current process onto a wait queue and it may also be run at the 
end of a system call, just before a process is returned to process mode from 
system mode. One reason that it might need to run is because the system timer 
has just set the current processes counter to zero. Each time the scheduler is
run it does the following: 
-->
<p>スケジューラは、カーネル内のいろいろな場所から実行される。それは現在走行中
のプロセスを待ち行列に入れたあとに実行され、またシステムコールが終了してプロ
セスがシステムモードからプロセスモードに戻る直前にも実行されるときがある。
スケジューラの実行が必要とされる理由は、システムタイマーがカレントプロセスの
カウンター(counter)をその時にゼロにセットするからである。<newline>
[see: schedule(), in <htmlurl 
url="The-Linux-Kernel-images/linux/kernel/sched.c" 
name="kernle/sched.c">]<newline>
スケジューラが実行されると、それは次のようなことをする。

<descrip>
<!--
kernel work
      The scheduler runs the bottom half handlers and processes the scheduler
      task queue. These lightweight kernel threads are described in detail in
      chapter  kernel-chapter. 
-->
<tag><tt>カーネルワーク(kernel work)</tt></tag>
スケジューラは、ボトムハーフハンドラ(bottom half handlers)を実行し、
スケジューラのタスクキューを処理する。これらのライトウェイトカーネルスレッド
(lightweight kernel threads)の詳細は、<ref id="chapter_km" 
name="「カーネルメカニズム」">の章で解説する。

<!--
Current process
      The current process must be processed before another process can be
      selected to run. 

      If the scheduling policy of the current processes is round robin then it
      is put onto the back of the run queue. 

      If the task is INTERRUPTIBLE and it has received a signal since the last
      time it was scheduled then its state becomes RUNNING. 

      If the current process has timed out, then its state becomes RUNNING. 

      If the current process is RUNNING then it will remain in that state. 

      Processes that were neither RUNNING nor INTERRUPTIBLE are removed
      from the run queue. This means that they will not be considered for 
      running when the scheduler looks for the most deserving process to run. 
-->
<tag><tt>カレントプロセス (Current process)</tt></tag>
次のプロセスを選んで実行する前に、現在走行中のプロセス(current process)が処理
されなければならない。
<p>走行中のプロセスのスケジューリングポリシーがラウンドロビンなら、そのプロセス
は実行キューの最後に置かれる。
<p>タスクが割り込み可能(INTERRUPTIBLE)で、最後にスケジューリングされてから
プロセスがシグナルを受け取っている場合、そのプロセスの <tt>
<ref id="task_struct" name="task_struct"></tt> の <tt>state</tt>が、走行中
(RUNNING)となる。
<p>現在走行中のプロセスが時間切れになった場合、その <tt>state</tt> は走行中
(RUNNING)となる。
<p>現在走行中のプロセスの <tt>state</tt> が走行中(RUNNING)の場合、その <tt>
state</tt> がそのまま維持される。
<p>走行中(RUNNING)でも割り込み可能(INTERRUPTIBLE)でもないプロセスは実行キュー
から削除される。すなわち、スケジューラが実行すべき最も優先度の高いプロセスを
探しているとき、それらは実行の対象とは見なされないということを意味する。

<!--
Process selection
      The scheduler looks through the processes on the run queue looking for 
      the most deserving process to run. If there are any real time processes 
      (those with a real time scheduling policy) then those will get a higher 
      weighting than ordinary processes. The weight for a normal process is 
      its counter but for a real time process it is counter plus 1000. 
      This means that if there are any runnable real time processes in the 
      system then these will always be run before any normal runnable 
      processes. The current process, which has consumed some of its 
      time-slice (its counter has been decremented) is at a disadvantage if 
      there are other processes with equal priority in the system; that is as 
      it should be. If several processes have the same priority, the one 
      nearest the front of the run queue is chosen. The current process will 
      get put onto the back of the run queue. In a balanced system with many 
      processes of the same priority, each one will run in turn.
      This is known as Round Robin scheduling. However, as processes wait for
      resources, their run order tends to get moved around. 
-->
<tag><tt>プロセス選択 (process selection)</tt></tag>
スケジューラは、実行キュー上のプロセスを見渡して、実行に最も値するプロセスを
探す。もしリアルタイムプロセスがあれば(それらはリアルタイムスケジューリング
ポリシーを持つ)、それらは通常のプロセスよりも重視される。通常のプロセスの
重要性はその <tt>counter</tt> で決まるが、リアルタイムプロセスに関してはその
 <tt>counter</tt> 値に 1000 が付加される。すなわち、システム内に実行可能な
リアルタイムプロセスがある場合、通常の実行可能などんなプロセスよりも必ず先に
実行されるということである。
現在走行中のプロセスは、タイムスライスの一部を消費してしまっている(プロセスの
 <tt>counter</tt> 値が減少している)ので、システム上の同じ優先度を持つプロセス
よりも不利な立場に立つ。それは当然そうなるべきである。多くのプロセスが
同一の優先順位を持つ場合、実行キューの先頭に最も近いものが選択される。現在の
プロセスは実行キューの最後に戻される。同一の優先順位にある多数のプロセス間で
システムのバランスを保つため、個々のプロセスは順番に実行される。これはラウン
ドロビンスケジューリングと呼ばれる。しかし、プロセスはリソースの取得を待つ
場合があるので、実行の順番は前後する傾向がある。

<!--
Swap processes
      If the most deserving process to run is not the current process, then the
      current process must be suspended and the new one made to run. When a
      process is running it is using the registers and physical memory of the
      CPU and of the system. Each time it calls a routine it passes its
      arguments in registers and may stack saved values such as the address to
      return to in the calling routine. So, when the scheduler is running it is
      running in the context of the current process. It will be in a privileged
      mode, kernel mode, but it is still the current process that is running. 
      When that process comes to be suspended, all of its machine state, 
      including the program counter (PC) and all of the processor's registers,
      must be saved in the processes task_struct data structure. Then, all of 
      the machine state for the new process must be loaded. This is a system 
      dependent operation, no CPUs do this in quite the same way but there is 
      usually some hardware assistance for this act. 
-->
<tag><tt>スワッププロセス (swap process)</tt></tag>
最優先で実行されるべきプロセスが現在のプロセスとは異なる場合、現在のプロセスは
停止状態にされ、新しいプロセスが実行される。プロセスは実行中に CPU やシステム
のレジスタや物理メモリを使用している。ルーチンをコールするたびに、プロセスは
レジスタ内の引数をルーチンに渡しているし、呼び出したルーチンから戻されるアドレ
ス等の保存すべき値をスタックに積む場合もある。
それゆえ、スケジューラが実行されている際、スケジューラはカレントプロセスの
コンテキスト(<ref id="chapter_p_context" name="context">)で実行される。
スケジューラは特権モードであるカーネルモードで動作しているのだが、
それでも実行されているのは、カレントプロセスである。
そのプロセスが停止されるべきときは、プログラムカウンタやすべてのプロセッサの
レジスタを含むそのマシンの状態(machine state)全体が、プロセスの <tt><ref 
id="task_struct" name="task_struct"></tt> データ構造体に保存されなければなら
ない。その後で、新しいプロセスのマシンの状態すべてがロードされる。
これはシステムに依存する操作であり、まったく同じ方法で動作する CPU はないのだ
が、この処理に対しては通常なんらかのハードウェアによる援助がなされる。

<!--
      This swapping of process context takes place at the end of the scheduler.
      The saved context for the previous process is, therefore, a snapshot of 
      the hardware context of the system as it was for this process at the end
      of the scheduler. Equally, when the context of the new process is 
      loaded, it too will be a snapshot of the way things were at the end of 
      the scheduler, including this processes program counter and register 
      contents. 
-->
この(新旧両プロセス間での)プロセスコンテキストの入れ替え(swapping)は、スケ
ジューラの処理の一番最後で実行される。直前のプロセスのために保存されたコンテキ
ストは、スケジューラの終わりの時点でのそのプロセスが所持した、システムのハード
ウェアコンテキストに関するスナップショットである。
同様に、新しいプロセスのコンテキストがロードされる時、それもまたスケジューラの
最後の時点におけるそのプロセスのスナップショットであり、それには、プロセスの
プログラムカウンタやレジスタの内容などが含まれている。

<!--
      If the previous process or the new current process uses virtual memory
      then the system's page table entries may need to be updated. Again, this
      action is architecture specific. Processors like the Alpha AXP, which use
      Translation Look-aside Tables or cached Page Table Entries, must flush
      those cached table entries that belonged to the previous process. 
-->
直前のプロセスや新しいプロセスが仮想メモリを使用する場合、システムのページ
テーブルエントリはアップデートされる必要がある。これもまたアーキテクチャ固有の
処理である。Alpha AXP のようなプロセッサの場合、アドレス変換バッファか
キャッシュされたページテーブルエントリを使用するので、直前のプロセスに属する
それらのキャッシュテーブルのエントリを無効にする必要がある。

</descrip>

<!--4.3.1  Scheduling in Multiprocessor Systems-->
<sect2>マルチプロセッサシステムでのスケジューリング

<!--
Systems with multiple CPUs are reasonably rare in the Linux world but a lot of
work has already gone into making Linux an SMP (Symmetric Multi-Processing)
operating system. That is, one that is capable of evenly balancing work between
the CPUs in the system. Nowhere is this balancing of work more apparent than in
the scheduler. 
-->
<p>複数の CPU を持つシステムは Linux の世界ではそれほど多くはないが、Linux を
 SMP(Symmetric Multi-Processing)対応のオペレーティングシステムにするための取
り組みは既に数多くなされている。すなわち、システム内の CPU 間の仕事量を均等に
分担させる仕組みなどである。スケジューラほどこの作業分担処理が顕著に現れると
ころはない。

<!--
In a multiprocessor system, hopefully, all of the processors are busily running
processes. Each will run the scheduler separately as its current process 
exhausts its time-slice or has to wait for a system resource. The first thing 
to notice about an SMP system is that there is not just one idle process in 
the system. In a single processor system the idle process is the first task in
the task vector, in an SMP system there is one idle process per CPU, and you 
could have more than one idle CPU. Additionally there is one current process 
per CPU, so SMP systems must keep track of the current and idle processes for 
each processor. 
-->
<p>マルチプロセッサのシステムでは、すべてのプロセッサが常時プロセスの実行にあ
たっていることが望ましい。個々の CPU 上の現在のプロセスがタイムスライスを使い
切ったり、システムリソースを待たなければならなくなったとき、CPU は独立してスケ
ジューラを実行する。SMP システムに関してまず注意するべきことは、システム内の
アイドル状態のプロセスはひとつではないということである。シングルプロセッサの
システムなら、アイドルプロセスは <tt><ref id="task" name="task"></tt> 配列の
最初のタスクであるが、SMP システムでは CPU ごとにアイドルプロセスが存在する。
加えて、カレントプロセスも CPU ごとに存在するので、SMP システムはカレント
プロセスとアイドルプロセスとを CPU ごとに監視しなければならない。

<!--
In an SMP system each process's task_struct contains the number of the
processor that it is currently running on (processor) and its processor number
of the last processor that it ran on (last_processor). There is no reason why a
process should not run on a different CPU each time it is selected to run but 
Linux can restrict a process to one or more processors in the system using the
processor_mask. If bit N is set, then this process can run on processor N.
When the scheduler is choosing a new process to run it will not consider one 
that does not have the appropriate bit set for the current processor's number 
in its processor_mask. The scheduler also gives a slight advantage to a 
process that last ran on the current processor because there is often a 
performance overhead when moving a process to a different processor. 
-->
<p>SMP システムでは、個々のプロセスの <tt><ref id="task_struct" 
name="task_struct">_</tt> 構造体は、現在プロセスが走行中のプロセッサの番号
(<tt><ref id="task_struct" name="processor"></tt>)、およびそのプロセスが前回実
行されたプロセッサの番号(<tt><ref id="task_struct" name="last_processor"></tt>)
という情報を含む。
プロセスが選ばれるたびに違うプロセッサ上で実行されることがいけないという理由は
ないが、Linux は、<tt><ref id="processor_mask" name="processor_mask"></tt> を
使用して、プロセスがシステム
上の特定のプロセッサしか使わないよう制限することができる。ビット N がセットされ
ると、そのプロセスはプロセッサ N 上で実行が可能になる。スケジューラが、実行すべ
き新しいプロセスを選んでいるとき、割り当てを行おうとするプロセッサ番号に
適した番号が <tt>processor_mask</tt> にセットされていないプロセスは候補から
除外する。また、前回実行されたプロセッサとは異なるプロセッサ上でプロセスを
実行するときは、しばしばパフォーマンス上のオーバーヘッドが生じるので、
あるプロセスが、これから割り付けを行うプロセッサを前回も使っていた
場合は、スケジューラはそのプロセスに対し若干のアドバンテージを与える。


<!--4.4  Files-->
<sect1>ファイル<label id="chapter_p_sect4">
<p>


<!--                    Figure 4.1: A Process's Files-->
<#if output="html">
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/figure4-1.gif">
</figure>
</#if>
<#unless output="html">
<verb>
                   fs_struct                inode
                  +----------+             +------+
              +-->| count    |      +----->|      |
 task_struct  |   |----------|      |      |      |
              |   | unmask   |0x022 |      |      |
|           | |   |----------|      |      |      |
|           | |   | *next    |------+      +------+
|-----------+ |   |----------|
| fs        |-+   | *prev    |------+
|-----------+     +----------+      |       inode
| files     |-+                     |      +------+
|-----------+ |                     +----->|      |
|           | |                            |      |
|           | |    files_struct            |      |
              |   +---------------+        |      |
              +-->| count         |        +------+
                  |---------------|
                  | close_on_exec |
                  |---------------|
                  | open_fs       |
                  |---------------|                          inode
                  | fd[0]         |     file               +------+
                  |---------------|   +--------------+ +-->|      |
                  | fd[1]         |-->| f_mode       | |   |      |
                  |---------------|   |--------------| |   |      |
                  |               |   | f_ps         | |   |      |
                  |               |   |--------------| |   +------+
                  |               |   | f_flags      | |
                  |               |   |--------------| |
                  |               |   | f_count      | |
                  |               |   |--------------| |
                  |---------------|   | f_owner      | |
                  | fd[255]       |   |--------------| |
                  +---------------+   | f_inode      |-+
                                      |--------------|
                                      | f_op         |--->ファイル
                                      |--------------|    操作
                                      | f_version    |    ルーチン
                                      +--------------+
</verb>
</#if>
<p>図表(4.1) プロセスのファイル

<!--
Figure  4.1 shows that there are two data structures that describe file system
specific information for each process in the system. The first, the fs_struct 
contains pointers to this process's VFS inodes and its umask. The umask is the
default mode that new files will be created in, and it can be changed via 
system calls. 
-->
<p>図表 4.1 では、ふたつのデータ構造があり、システム上の個々のプロセスに関する
ファイルシステム固有の情報を記述している仕組みが示されている。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/linux/sched.h" 
name="include/linux/sched.h">]<newline>
ひとつめの、<tt><ref id="fs_struct" name="fs_struct"></tt> は
当該プロセスの VFS <tt><ref id="inode" name="inode"></tt> とその <tt>
umask</tt> に対するポインタを含んでいる。
<tt>umask</tt> とは新しいファイルが作成される際のデフォルトモードであり、
そのモードはシステムコールを介して変更可能である。

<!--
The second data structure, the files_struct, contains information about all of
the files that this process is currently using. Programs read from standard 
input and write to standard output. Any error messages should go to standard 
error. These may be files, terminal input/output or a real device but so far 
as the program is concerned they are all treated as files. Every file has its 
own descriptor and the files_struct contains pointers to up to 256 file data 
structures, each one describing a file being used by this process. The f_mode 
field describes what mode the file has been created in; read only, read and 
write or write only. f_pos holds the position in the file where the next read 
or write operation will occur. f_inode points at the VFS inode describing the 
file and f_ops is a pointer to a vector of routine addresses; one for each 
function that you might wish to perform on a file. There is, for example, a 
write data function. This abstraction of the interface is very powerful and 
allows Linux to support a wide variety of file types. In Linux, pipes are 
implemented using this mechanism as we shall see later. 
-->
<p>ふたつめのデータ構造である <tt><ref id="files_struct" name="files_struct">
</tt> には、そのプロセスが現在使用しているすべてのファイルに関する情報が含まれ
る。プログラムは標準入力(standard input)から読み込みをし、標準出力(standard 
output)に書き出す。すべてのエラーメッセージは標準エラー(standard error)に送ら
れる。
それらはファイルであったり、ターミナルへの入出力であったり、実デバイスであった
りするが、そのプログラムに関する限り、それらはすべてファイルとして扱われる。
すべてのファイルは自分自身の記述子(descriptor)を持っており、<tt>files_struct
</tt> は、256 までの <tt><ref id="file" name="file"></tt> データ構造体に対す
るポインタを含むことができ、それらの各々がそのプロセスで使用されている
ファイルを指し示している。<tt><ref id="file" name="file"></tt> 構造体の 
<tt><ref id="file" name="f_mode"></tt> フィールドはそのファイルがどのモードで
作成されているのかを示す。読み込み専用、読み書き可能、書き込み専用などである。
<tt><ref id="file" name="f_pos"></tt> はファイル内の位置情報を保持していて、
次の読み書き処理がファイル内のどこでなされるかを示している。
<tt><ref id="file" name="f_inode"></tt> は、そのファイルを記述する VFS <tt>
<ref id="inode" name="inode"></tt> をポイントしており、<tt>f_ops</tt>
(訳注: <tt><ref id="file" name="f_op"></tt>？) は、ルーチンのアドレスの配列に
対するポインタであり、個々のルーチンは、たとえば、データ書き込みのための関数な
どの、そのファイルに対する操作の際に呼び出される関数である。
このインターフェイスの抽象化は非常にパワフルであり、それによって Linux は
幅広いファイルタイプをサポートすることができる。Linux では、このメカニズムを
利用したパイプが実装されているが、それについては後ほど述べる。

<!--
Every time a file is opened, one of the free file pointers in the files_struct
is used to point to the new file structure. Linux processes expect three file
descriptors to be open when they start. These are known as standard input,
standard output and standard error and they are usually inherited from the 
creating parent process. All accesses to files are via standard system calls 
which pass or return file descriptors. These descriptors are indices into the 
process's fd vector, so standard input, standard output and standard error 
have file descriptors 0, 1 and 2. Each access to the file uses the file data 
structure's file operation routines to together with the VFS inode to achieve 
its needs. 
-->
<p>ファイルがオープンされるたびに、<tt><ref id="files_struct" 
name="file_struct"></tt> 内にある使用されていない <tt><ref id="file" 
name="file"></tt> へのポインタが新しい <tt>file</tt> 構造体に対するポインタ
として使用される。
Linux のプロセスは、実行される際に 3 つのファイルディスクリプタがあることを
前提にしている。
それらは、標準入力、標準出力、標準エラーと呼ばれ、通常生成に関与し
た親プロセスからそれらを受け継ぐ。ファイルへのアクセスはすべて標準
システムコール経由で行われ、それらのシステムコールとの間でファイルディスクリ
プタのやり取りがある。これらのファイルディスクリプタは、プロセスの <tt>
<ref id="files_struct" name="fd"></tt> 
配列へのインデックスとなっていて、標準入力、標準出力、標準エラーは
それぞれ 0, 1, 2 のファイルディスクリプタを持つ。ファイルへのアクセスのたびに
 <tt>file</tt> データ構造のファイル操作ルーチンと、VFS inode とを使用し、
目的とする必要な処理が行われる。

<!--4.5  Virtual Memory-->
<sect1>仮想メモリ<label id="chapter_p_sect5">

<!--
A process's virtual memory contains executable code and data from many
sources. First there is the program image that is loaded; for example a command
like ls. This command, like all executable images, is composed of both 
executable code and data. The image file contains all of the information 
neccessary to load the executable code and associated program data into the 
virtual memory of the process. Secondly, processses can allocate (virtual) 
memory to use during their processing, say to hold the contents of files that 
it is reading. This newly allocated, virtual, memory needs to be linked into 
the process's existing virtual memory so that it can be used. Thirdly, Linux 
processes use libraries of commonly useful code, for example file handling 
routines. It does not make sense that each process has its own copy of the 
library, Linux uses shared libraries that can be used by several running 
processes at the same time. The code and the data from these shared libraries 
must be linked into this process's virtual address space and also into the 
virtual address space of the other processes sharing the library. 
-->
<p>プロセスの仮想メモリに含まれる実行コードとデータは、様々なソースから成り
立っている。
第一に、ロードされるべきプログラムイメージがある。たとえば、<tt>ls</tt> のよう
なコマンドは、他のすべての実行イメージ同様、実行コードとデータから構成されて
いる。そのイメージファイルには、実行コードとプログラムの関連データとを
プロセスの仮想メモリにロードするのに必要なすべての情報も含まれている。
第二に、プロセス自体が、新たに仮想メモリを割り付ける場合がある。これは、読み出
し中のファイルの内容の保持するときなどに、そのプロセスの処理中に使用されるもの
である。この新しく割り付けられた仮想メモリを使えるようにするには、プロセスの
持つ既存の仮想メモリにリンクしなければならない。
第三に、Linux のプロセスは、たとえばファイルハンドリングのルーチンなど、一般的
によく利用されるコードであるライブラリを使用する。個々のプロセスが自分自身の
ライブラリのコピーを持つのでは意味がないので、Linux はいくつかの実行中の
プロセスから同時に使用することが可能な共有ライブラリを使用している。そうした
共有ライブラリのコードやデータも、そのプロセスの仮想アドレス空間にリンクされ
なければならない。また、それらは、ライブラリを共有している他のプロセスの
仮想アドレス空間にもリンクされなければならない。

<!--
In any given time period a process will not have used all of the code and data
contained within its virtual memory. It could contain code that is only used 
during certain situations, such as during initialization or to process a 
particular event. It may only have used some of the routines from its shared 
libraries. It would be wasteful to load all of this code and data into 
physical memory where it would lie unused. Multiply this wastage by the number
of processes in the system and the system would run very inefficiently. 
Instead, Linux uses a technique called demand paging where the virtual memory 
of a process is brought into physical memory only when a process attempts to 
use it. So, instead of loading the code and data into physical memory straight
away, the Linux kernel alters the process's page table, marking the virtual 
areas as existing but not in memory. When the process attempts to acccess the 
code or data the system hardware will generate a page fault and hand control 
to the Linux kernel to fix things up. Therefore, for every area of virtual 
memory in the process's address space Linux needs to know where that virtual 
memory comes from and how to get it into memory so that it can fix up
these page faults. 
-->
<p>ある限られた時間の単位で眺めれば、プロセスは仮想メモリ内に含まれるコードや
データのすべてを使っているわけではない。特定の状況でしか利用されないコード、
たとえば初期化や特別なイベントを処理するときだけしか使用されないコードも仮想
メモリに含まれている。共有ライブラリのルーチンも僅かしか使用していないかも
しれない。
そうしたコードやデータのすべてを物理メモリにロードして、使わずに放っておく
のは資源の無駄である。システム上のプロセスの数だけこの無駄があるとすると、
システムを実行する上で非常に効率が悪い。これに対処するために、Linux は、
デマンドページングというテクニックを使用し、プロセスがその仮想メモリを使用
するときだけその仮想メモリを物理メモリに戻すようにしている。したがって、
コードやデータを物理メモリに直接ロードするかわりに、Linux カーネルはプロセス
のページテーブルを変更し、仮想エリアを存在はするが(訳注: valid だが)物理メモリ
内には存在しない状態にしている。
プロセスがコードやデータにアクセスしようとすると、システムのハードウェアが
ページフォルトを起こし、制御を Linux カーネルに渡して、カーネルが問題を解決
するようになっている。
それゆえ、そうしたページフォルトに対処するために、プロセスのアドレス空間にある
仮想メモリのすべての領域に関して、Linux は、仮想メモリがどういったソースから
成り立つもので、どうすれば物理メモリ内に取ってこれるのかを知っている必要があ
る。

<label id="figure4-2">
<!--                Figure 4.2: A Process's Virtual Memory-->
<#if output="html">
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/figure4-2.gif">
</figure>
</#if>
<#unless output="html">
<verb>
                                          プロセス仮想メモリ
                                             +----------+
task_struct                                  |          |
|        |                                   |          |
|        |                                   |          |
|        |    mm_struct    vm_area_struct +->|----------|
|--------|  +----------+    +----------+  |  |          |
|  mm    |->| count    | +->| vm_end   |--+  |          |
|--------|  |----------| |  |----------|     |          |
|        |  | pgd      | |  | vm_start |--+  |   Data   |
|        |  |----------| |  |----------|  |  |          |
|        |  |          | |  | vm_flag  |  |  |          |
|        |  |          | |  |----------|  |  |          |
|           |          | |  | vm_inode |  |  |          |
            |----------| |  |----------|  +->|----------|0x8059BB8
            | mmap     |-+  | vm_ops   |     |          |
            |----------|    |----------|     |          |
            | mmap_avi |    |          |     |          |
            |----------|    |          |     |          |
            | mmap_sem |    |----------|  +->|----------|
            +----------+    | vm_next  |-+|  |          |
                            +----------+ ||  |          |
                         +---------------+|  |          |
                         | vm_area_struct |  |          |
                         |  +----------+  |  |          |
                         +->| vm_end   |--+  |          |
                            |----------|     |          |
                            | vm_start |---->|----------|0x8048000
                            |----------|     |          |
                            | vm_flag  |     |          |
                            |----------|     |          |
                            | vm_inode |     |          |
                            |----------|     |          |
                            | vm_ops   |     |          |
                            |----------|     |          |
                            |          |     |          |
                            |          |     |          |
                            |----------|     |          |
                            | vm_next  |     |          |
                            +----------+     |          |
                                             +----------+ 0x0000000
</verb>
</#if>
<p>図表(4.2) プロセスの仮想メモリ

<!--
The Linux kernel needs to manage all of these areas of virtual memory and the
contents of each process's virtual memory is described by a mm_struct data
structure pointed at from its task_struct. The process's mm_struct data 
structure also contains information about the loaded executable image and
a pointer to the process's page tables. It contains pointers to a list of
vm_area_struct data structures, each representing an area of virtual memory 
within this process. 
-->
<p>Linux カーネルはそうした仮想メモリの領域全体を管理する必要があり、個々の
プロセスの仮想メモリの内容は、そのプロセスの<tt><ref id="task_struct" 
name="task_struct"></tt> からポイントされた <tt><ref id="mm_struct" 
name="mm_struct"></tt> データ構造体によって記述されている。
プロセスの <tt>mm_struct</tt> データ構造体は、ロードされた実行イメージに関す
る情報とプロセスのページテーブルへのポインタも含んでいる。また、<tt>mm_struct
</tt> には、<tt><ref id="vm_area_struct" name="vm_area_struct"></tt> 
データ構造体のリストに対するポインタが含まれていて、個々の 
<tt><ref id="vm_area_struct" name="vm_area_struct"></tt> 構造体は、
プロセス内の仮想メモリの領域を表現している。

<!--
This linked list is in ascending virtual memory order, figure  4.2 shows the 
layout in virtual memory of a simple process together with the kernel data 
structures managing it. As those areas of virtual memory are from several 
sources, Linux abstracts the interface by having the vm_area_struct point to 
a set of virtual memory handling routines (via vm_ops). This way all of the 
process's virtual memory can be handled in a consistent way no matter how the 
underlying services managing that memory differ. For example there is a 
routine that will be called when the process attempts to access the memory 
and it does not exist, this is how page faults are handled. 
-->
<p>この <tt><ref id="vm_area_struct" name="vm_area_struct"></tt> の連結リスト
は、仮想メモリアドレスの昇順に並べられている。<ref id="figure4-2" 
name="図表(4.2)">では、単純なプロセスの仮想メモリ内のレイアウトが、それを管理
するカーネルのデータ構造と一緒に示されている。仮想メモリの領域はいく
つものソースから成立しているので、Linux はそのインターフェイスを抽象化
するために、<tt>vm_area_struct</tt> を使って(<tt><ref id="vm_area_struct" 
name="vm_ops"></tt>経由で)、仮想メモリ操作の一連のルーチンをポイントしている。
この方法により、プロセスの仮想メモリはすべて一貫した方法で操作できる
ようになっており、その操作方法は、仮想メモリを管理する基礎的な
サービスがどのように異なっていても変わらない。たとえば、プロセスが仮想メモリに
アクセスしようとしたがそれが物理メモリ上に存在しなかったときに呼び出される
ルーチンがある。ページフォルトを処理する場合に使用されるのが、そのルーチン
である。

<!--
The process's set of vm_area_struct data structures is accessed repeatedly
by the Linux kernel as it creates new areas of virtual memory for the process 
and as it fixes up references to virtual memory not in the system's physical 
memory. This makes the time that it takes to find the correct vm_area_struct 
critical to the performance of the system. To speed up this access, Linux also
arranges the vm_area_struct data structures into an AVL (Adelson-Velskii and 
Landis) tree. This tree is arranged so that each vm_area_struct (or node) has 
a left and a right pointer to its neighbouring vm_area_struct structure. The 
left pointer points to node with a lower starting virtual address and the 
right pointer points to a node with a higher starting virtual address. To 
find the correct node, Linux goes to the root of the tree and follows each 
node's left and right pointers until it finds the right vm_area_struct. Of 
course, nothing is for free and inserting a new vm_area_struct into this tree 
takes additional processing time. 
-->
<p>プロセスが持つ一連の <tt><ref id="vm_area_struct" 
name="vm_area_struct"></tt> データ構造体は、Linux カーネル
から繰り返しアクセスされる。たとえば、Linux が、そのプロセスのために新しい仮想
メモリのエリアを作成するときや、システムの物理メモリ内にない仮想メモリが
参照された場合にそれを解決するときなどである。
それゆえ、正しい <tt>vm_area_struct</tt> を発見するのにかかる時間は、
システムのパフォーマンスに深刻な影響を与える。このアクセス時間を短縮するため
に、Linux は、AVL (Adelson-Velskii and Landis) ツリーのなかに <tt>
vm_area_struct</tt> データ構造体を配置している。このツリーは、個々の <tt>
vm_area_struct</tt> (あるいは、ノード) が左右両隣の <tt>vm_area_struct</tt> 
データ構造体へのポインタを持つように配置されている。左のポインタは、それより
低い仮想アドレスを持つノードをポイントしており、右のポインタはそれより高い
仮想アドレスを持つノードをポイントしている。正しいノードを発見する際、
Linux はツリーの根(root)の部分から入って、個々のノードの左右のポインタを辿り、
正しい <tt>vm_area_struct</tt> を発見する仕組みになっている。
もちろん、この方法もいいことずくめではなく、このツリーに新しい <tt>
vm_area_struct</tt> を追加する場合、(通常より)多くのプロセス時間が消費される。

<!--
When a process allocates virtual memory, Linux does not actually reserve
physical memory for the process. Instead, it describes the virtual memory by
creating a new vm_area_struct data structure. This is linked into the process's
list of virtual memory. When the process attempts to write to a virtual address
within that new virtual memory region then the system will page fault. The
processor will attempt to decode the virtual address, but as there are no Page
Table Entries for any of this memory, it will give up and raise a page fault
exception, leaving the Linux kernel to fix things up. Linux looks to see if 
the virtual address referenced is in the current process's virtual address 
space. If it is, Linux creates the appropriate PTEs and allocates a physical 
page of memory for this process. The code or data may need to be brought into 
that physical page from the filesystem or from the swap disk. The process can 
then be restarted at the instruction that caused the page fault and, this time
as the memory physically exists, it may continue. 
-->
<p>プロセスが仮想メモリの割り付けを行うとき、Linux は実際にそのプロセスのため
の物理メモリを確保するわけではない。そのかわり、Linux は、新しく <tt>
<ref id="vm_area_struct" name="vm_area_struct"></tt> データ構造体を作成すること
でその仮想メモリを記述する。
この構造体はプロセスの仮想メモリのリストにリンクされる。プロセスがその新しい仮
想メモリの領域内にある仮想メモリに書き込みを行おうとするとき、システムはページ
フォルトを起こす。プロセッサは仮想アドレスを(物理アドレスに)デコードしようと
するが、その仮想メモリに関するページテーブルエントリ(PTE)が存在しないので、
諦めてページフォルト例外(page fault exception)を発行し、Linux カーネルに後の
処理を任せる。Linux は、参照された仮想アドレスが現在のプロセスの仮想アドレス
空間にあるかどうかを確認する。もしあるなら、Linux は適切な PTE を作成し、この
プロセスにメモリの物理ページを割り付ける。ファイルシステムやスワップディスク
から、コードやデータをその物理ページへと持って来なければならない場合もある。
それによって、プロセスはページフォルトの原因となった命令の時点から再始動さ
れ、今回は物理メモリが存在するので、実行が継続する。

<!--4.6  Creating a Process-->
<sect1>プロセスの生成<label id="chapter_p_sect6">

<!--
When the system starts up it is running in kernel mode and there is, in a 
sense, only one process, the initial process. Like all processes, the initial 
process has a machine state represented by stacks, registers and so on. These 
will be saved in the initial process's task_struct data structure when other 
processes in the system are created and run. At the end of system 
initialization, the initial process starts up a kernel thread (called init) 
and then sits in an idle loop doing nothing. Whenever there is nothing else to
do the scheduler will run this, idle, process. The idle process's task_struct 
is the only one that is not dynamically allocated, it is statically defined at
kernel build time and is, rather confusingly, called init_task. 
-->
<p>システムは、起動時に、カーネルモードで実行されていて、その際は、ある意味
で、たったひとつのプロセスである初期化プロセスしか存在しない。
初期化プロセスも、他のすべてのプロセスと同様に、スタックやレジスタなどで表現
されるマシン状態(machine state)を持っている。
他のプロセスが生成されて実行される時、それらの情報は、初期化プロセスの 
<tt><ref id="task_struct" name="task_struct"></tt> データ構造体に保存される。
システムの初期化が終了した時点
で、初期化プロセスは、(<tt>init</tt> と呼ばれる)カーネルスレッド(kernel 
thread)を起動し、アイドルループ(idle loop)状態に入って、何もしなくなる。
他に全く何もすることがなければ、スケジューラは、このアイドルプロセスを実行す
る。このアイドルプロセスの <tt>task_struct</tt> は、唯一、動的に割り付けを
されないプロセスであり、それはカーネルがビルドされた時に静的に定義されて
いるプロセスであり、やや紛らわしい名前だが、<tt>init_task</tt> と呼ばれてい
る。

<!--
The init kernel thread or process has a process identifier of 1 as it is the
system's first real process. It does some initial setting up of the system 
(such as opening the system console and mounting the root file system) and 
then executes the system initialization program. This is one of /etc/init, 
/bin/init or /sbin/init depending on your system. The init program uses
/etc/inittab as a script file to create new processes within the system. These
new processes may themselves go on to create new processes. For example the
getty process may create a login process when a user attempts to login. All of
the processes in the system are descended from the init kernel thread. 
-->
<p><tt>init</tt> というカーネルスレッドもしくはプロセスは、システムで最初の
実プロセスなので、プロセス識別子 1 を持っている。それは、システムの初期化
設定のいくつか(システムコンソールのオープンやルートファイルシステムのマウント
など)を実行し、その後でシステムの初期化プログラムを実行する。そのプログラムは、
システムに依存するので、<tt>/etc/init</tt>, <tt>/bin/init</tt>, もしくは
 <tt>/sbin/init</tt> のいずれかとなっている。<tt>init</tt> プログラムは、
スクリプトファイルとして <tt>/etc/inittab</tt> を使用して、システム上で新しい
プロセスを生成する。それらの新しいプロセスはそれ自体でさらに新しいプロセスを
生成する場合もある。たとえば、<tt>getty</tt> プロセスは、ユーザがログインしよう
とする時、<tt>login</tt> プロセスを生成する。システム内のすべてのプロセスは、
その <tt>init</tt> カーネルスレッドの子孫である。

<!--
New processes are created by cloning old processes, or rather by cloning the
current process. A new task is created by a system call (fork or clone) 
and the cloning happens within the kernel in kernel mode. At the end of the 
system call there is a new process waiting to run once the scheduler chooses 
it. A new task_struct data structure is allocated from the system's physical 
memory with one or more physical pages for the cloned process's stacks (user 
and kernel). A new process identifier may be created, one that is unique 
within the set of process identifiers in the system. However, it is perfectly 
reasonable for the cloned process to keep its parents process identifier. The 
new task_struct is entered into the task vector and the contents of the old 
(current) process's task_struct are copied into the cloned task_struct. 
-->
<p>新しいプロセスは、古いプロセスをクローニングするか、もしくは現在のプロセス
をクローニングすることで生成される。
<newline>[see: do_fork(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/fork.c" 
name="kernel/fork.c">]<newline>
新しいタスクはシステムコール(<tt>fork</tt> もしくは <tt>clone</tt> )によって
生成され、クローニングはカーネル内でカーネルモードにおいて実行される。
そのシステムコールが終了すると、新しいプロセスが誕生し、スケジューラが選択し
たならすぐに実行できる状態で待機している。新しい <tt><ref id="task_struct" 
name="task_struct"></tt> データ
構造体には、クローニングされたプロセスの(ユーザおよびカーネル)スタックのため
に、いくつかの物理ページが、システムの物理メモリから割り付けられる。新しい
プロセスの識別子が作成されるが、その識別子は、システム内にある一連のプロセス
識別子のなかでユニークなものである。しかし、クローニングされたプロセスがその
親プロセスの識別子を保持するという仕組みには、特別な合理的理由がある。
新しい <tt>task_struct</tt> が <tt>task</tt> 配列に追加され、古い方の(現在の)
プロセスの <tt>task_struct</tt> の内容がクローニングされたプロセスの新しい <tt>
task_struct</tt> にコピーされる。

<!--
When cloning processes Linux allows the two processes to share resources rather
than have two separate copies. This applies to the process's files, signal 
handlers and virtual memory. When the resources are to be shared their 
respective count fields are incremented so that Linux will not deallocate 
these resources until both processes have finished using them. So, for 
example, if the cloned process is to share virtual memory, its task_struct 
will contain a pointer to the mm_struct of the original process and that 
mm_struct has its count field incremented to show the number of current 
processes sharing it. 
-->
<p>クローニングの処理の際、Linux は、ふたつのプロセスが個別のリソースを持つ
のでなく、同じリソースを共有することが出来るようにしている。このことは、
プロセスのファイルやシグナルハンドラー、仮想メモリにもついても当てはまる。
リソースが互いに共有されるべき時は、リソースの <tt>count</tt> フィールドが
インクリメントされ、Linux は、両方のプロセスがそれを使うのを止めるまでそれら
のリソース
を解放しないようにする。したがって、たとえば、クローニングされたプロセスが仮想
メモリを共有しようとする場合、そのプロセスの <tt><ref id="task_struct" 
name="task_struct"></tt> には、元の(親)プロセスの <tt><ref id="mm_struct" 
name="mm_struct"></tt> へのポインタが含められ、親プロセスの 
<tt>mm_struct</tt> の <tt><ref id="mm_struct" name="count"></tt> フィールドが
加算されて、それを共有するプロセスの数が示される。

<!--
Cloning a process's virtual memory is rather tricky. A new set of
vm_area_struct data structures must be generated together with their owning
mm_struct data structure and the cloned process's page tables. None of the
process's virtual memory is copied at this point. That would be a rather 
difficult and lengthy task for some of that virtual memory would be in 
physical memory, some in the executable image that the process is currently 
executing and possibly some would be in the swap file. Instead Linux uses a 
technique called ``copy on write'' which means that virtual memory will only 
be copied when one of the two processes tries to write to it. Any virtual 
memory that is not written to, even if it can be, will be shared between the 
two processes without any harm occuring. The read only memory, for example the
executable code, will always be shared. For ``copy on write'' to work, the 
writeable areas have their page table entries marked as read only and the 
vm_area_struct data structures describing them are marked 
as ``copy on write''. When one of the processes attempts to write to this
virtual memory a page fault will occur. It is at this point that Linux will 
make a copy of the memory and fix up the two processes' page tables and 
virtual memory data structures. 
-->
<p>プロセスの仮想メモリのクローニングはややトリッキーである。<tt><ref 
id="vm_area_struct" name="vm_area_struct"></tt> データ構造体の新しいセットが、
それらを所有する <tt><ref id="mm_struct" name="mm_struct"></tt> データ
構造体とクローニングされたプロセスのページテーブルとともに生成される。プロセス
の仮想メモリはこの段階ではまだ複製されていない。それは面倒で時間の掛かるタスク
である。というのも、親プロセスの仮想メモリのうち、ある部分は物理メモリにある
かもしれないが、プロセスが現在実行している実行イメージの中にあるものもあり、
おそらくスワップファイルの中にあるものもあるからである。それゆえ、Linux は、
「コピーオンライト(copy on write)」と呼ばれるテクニックを使用する。その意味は、
ふたつのプロセスのうちのひとつがそれに書き込みをしようとするときだけその仮想
メモリがコピーされるというものである。書き込みが可能な場合でも、(書き込み要求
がないために)書き込まれていないそうした仮想メモリは、何の問題もなくふたつの
プロセス間で共有される。たとえば実行コードのような、読み込み専用のメモリは常に
共有される。
「コピーオンライト」方式を機能させる場合、書き込み可能なエリアは、そのページ
テーブルエントリを読み込み専用とマークし、それらのエリアを記述する 
<tt>vm_area_struct</tt> データ構造体を「コピーオンライト」とマークする。
共有プロセスのひとつがこの仮想メモリに書き込みをしようとすると、ページフォルト
が起こる。この時点で、Linux はメモリのコピーを作成し、ふたつのプロセスのページ
テーブルと仮想メモリのデータ構造を訂正する。

<!--4.7  Times and Timers-->
<sect1>時間とタイマー<label id="chapter_p_sect7">

<!--
The kernel keeps track of a process's creation time as well as the CPU time 
that it consumes during its lifetime. Each clock tick, the kernel updates the 
amount of time in jiffies that the current process has spent in system and in 
user mode. 
-->
<p>カーネルは、プロセスが生成される時間を監視すると同時に、それがライフサイクル
において消費する CPU 時間も監視している。クロックティック(<ref id="clock_tick" 
name="clock tick">)ごとに、
カーネルは、現在のプロセスがシステムモードおよびユーザモードで消費した時間の
総量を <tt>jiffies</tt> 値を使って計測・更新している。

<!--
In addition to these accounting timers, Linux supports process specific 
interval timers. A process can use these timers to send itself various signals
each time that they expire. Three sorts of interval timers are supported: 
-->
<p>そうした時間記録用のタイマーに加えて、Linux はプロセス固有のインターバル
タイマー(interval timer)もサポートしている。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/itimer.c" 
name="kernel/itimer.c">]<newline>
プロセスはそのタイマーを使用して、タイマーの所定時間が経過するごとに自分自身
に対して様々なシグナルを送っている。サポートされている三種類のインターバル
タイマーには、次のようなものがある。

<descrip>
<!--
Real the timer ticks in real time, and when the timer has expired, the process
     is sent a SIGALRM signal. 
-->
<tag><tt>real</tt></tag>
実時間で計測されるタイマチック(<ref id="clock_tick" name="timer tick">)。その
タイマーの所定時間が経過すると、プロセスに <tt>SIGALRM</tt> シグナルが送られ
る。

<!--
Virtual This timer only ticks when the process is running and when it expires 
        it sends a SIGVTALRM signal. 
-->
<tag><tt>virtual</tt></tag>
プロセスの実行中だけ計測されるタイマチック。所定時間が経過すると、プロセス
に <tt>SIGVTALRM</tt> シグナルを送る。

<!--
Profile This timer ticks both when the process is running and when the system 
        is executing on behalf of the process itself. SIGPROF is signalled 
        when it expires. 
-->
<tag><tt>profile</tt></tag>
プロセスの実行時と、プロセスを代理してシステムが実行されている時の両方で
計測されるタイマチック。所定時間経過により <tt>SIGPROF</tt> シグナルを送
る。

</descrip>

<!--
One or all of the interval timers may be running and Linux keeps all of the
neccessary information in the process's task_struct data structure. System
calls can be made to set up these interval timers and to start them, stop them
and read their current values. The virtual and profile timers are handled the 
same way. Every clock tick the current process's interval timers are 
decremented and, if they have expired, the appropriate signal is sent. 
-->
<p>ひとつもしくはすべてのインターバルタイマーを実行することが可能で、Linux 
はそれらすべての必要な情報をプロセスの <tt><ref id="task_struct" 
name="task_struct"></tt> データ構造体に保存する。これらのインターバルタイマー
の設定、始動、停止および現在の値の読みとりは、システムコールにより実行される。
<newline>[see: do_it_virtual(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/sched.c" 
name="kernel/sched.c">]
<newline>[see: do_it_prof(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/sched.c" 
name="kernel/sched.c">]<newline>
virtual および profile タイマーは、同じ方法で操作される。クロックティックごとに
走行中のプロセスのインターバルタイマーの値は減少し、所定時間経過により、適切
なシグナルが送られる。

<!--
Real time interval timers are a little different and for these Linux uses the 
timer mechanism described in Chapter  kernel-chapter. Each process has its own
timer_list data structure and, when the real interval timer is running, this is
queued on the system timer list. When the timer expires the timer bottom half
handler removes it from the queue and calls the interval timer handler. This 
generates the SIGALRM signal and restarts the interval timer, adding it back 
into the system timer queue. 
-->
<p>リアルタイム(real time)インターバルタイマーはそれとは少し異
なり、Linux は、そのために<ref id="chapter_km" name="「カーネルの仕組み」">の
章で解説するタイマーメカニズムを使用する。
<newline>[see: it_real_fn(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/kernel/itimer.c" 
name="kernel/itimer.c">]<newline>
個々のプロセスは、自分の <tt><ref id="timer_list" name="timer_list"></tt> 
データ構造体を持ち、リアル(real)インターバルタイマーが実行されているとき、その
構造体がシステムタイマーリストのキューに入る。所定時間が経過すると、タイマー
のボトムハーフハンドラー(bottom half handler)がそれをキューから削除し、インター
バルタイマーハンドラー(interval timer handler)を呼び出す。そしてそれが 
<tt>SIGALRM</tt> シグナルを生成し、インターバルタイマーを再始動させ、当該
構造体を再度システムタイマーのキューに戻す。

<!--4.8  Executing Programs-->
<sect1>プログラムの実行<label id="chapter_p_sect8">

<!--
In Linux, as in Unix TM, programs and commands are normally executed by a
command interpreter. A command interpreter is a user process like any other
process and is called a shell 2. There are many shells in Linux, some of the 
most popular are sh, bash and tcsh. With the exception of a few built in 
commands, such as cd and pwd, a command is an executable binary file. For 
each command entered, the shell searches the directories in the process's 
search path, held in the PATH environment variable, for an executable image 
with a matching name. If the file is found it is loaded and executed. The 
shell clones itself using the fork mechanism described above and then the new 
child process replaces the binary image that it was executing, the shell, 
with the contents of the executable image file just found. Normally the shell 
waits for the command to complete, or rather for the child process to exit. 
You can cause the shell to run again by pushing the child process to the 
background by typing control-Z, which causes a SIGSTOP signal to be sent to 
the child process, stopping it. You then use the shell command bg to push it 
into a background, the shell sends it a SIGCONT signal to restart it, where 
it will stay until either it ends or it needs to do terminal input or output. 
-->
<p>Linux では、他の Unix と同様に、プログラムやコマンドは、通常コマンドイン
タープリタによって実行される。コマンドインタープリタは、他のプロセス同様
ユーザプロセスであり、シェル(<ref id="chapter_p_fn1" name="脚注 2">)と呼ばれ
る。Linux 上には多くのシェルがあり、
最も有名なものとして、<tt>sh, bash</tt> そして <tt>tcsh</tt> がある。<tt>cd
</tt> や <tt>pwd</tt> といったいくつかの組み込みコマンドを除けば、
コマンドとは実行可能なバイナリファイルのことである。コマンドが入力されると、
シェルは、環境変数 <tt>PATH</tt> に設定されたプロセスの検索パス内のディレクトリ
を探し、同じ名前の実行イメージを見つけようとする。そのファイルが見つかれば、
それはロードされ実行される。シェルは、<tt>fork</tt> という仕組みを使って、
先ほど説明したように自分自身をクローニングする。そして、次に新しい子プロセス
は、親プロセスが実行していたバイナリイメージ、すなわちシェルを、見つかった
ばかりの実行イメージの内容と置き換える。通常、シェルは、そのコマンドの完了、
言い換えると子プロセスの終了を待つ。シェルを再度走らせたいときは、control-Z 
とタイプして、子プロセスをバックグラウンドに押しやればよい。これは、子プロセス
に <tt>SIGSTOP</tt> シグナルを送って、それを停止させる操作である。次に、
シェルコマンド <tt>bg</tt> を使って子プロセスをバックグラウンドに押しやること
もできる。これは、シェルから子プロセスに対して <tt>SIGCONT</tt> シグナルを
送って再始動させるもので、子プロセスは実行が終了するか、ターミナルでの入出力
が必要になるまでそこに留まる。

<!--
An executable file can have many formats or even be a script file. Script 
files have to be recognized and the appropriate interpreter run to handle 
them; for example /bin/sh interprets shell scripts. Executable object files 
contain executable code and data together with enough information to allow the
operating system to load them into memory and execute them. The most commonly 
used object file format used by Linux is ELF but, in theory, Linux is flexible
enough to handle almost any object file format. 
-->
<p>実行ファイルは多種のフォーマットを取ることができる。
それは、スクリプトファイルであってもよい。
スクリプトファイルは解釈可能なものでなければならず、適切なインター
プリタを実行してそれを処理しなければならない。たとえば、<tt>/bin/sh</tt> は、
シェルスクリプトを解釈するインタープリタである。実行可能なオブジェクトファイ
ルには、実行コードとデータ、およびオペレーティングシステムがそれをメモリに
ロードして実行することができるだけの充分な情報が含まれている。Linux 上で最も
一般的に利用されているオブジェクトファイルのフォーマットは、ELF であるが、
理論上は、Linux は、ほとんどすべてのオブジェクトファイルのフォーマットを扱え
るだけの柔軟性をもっている。


<!--                Figure 4.3: Registered Binary Formats-->
<#if output="html">
<figure><ph vspace="1"><img src="./The-Linux-Kernel-images/figure4-3.gif">
</figure>
</#if>
<#unless output="html">
<verb>
formats   linux_binfmt          linux_binfmt           linux_binfmt
        +----------------+    +----------------+    +----------------+
------->| next           |--->| next           |--->| next           |
        |----------------|    |----------------|    |----------------|
        | use_count      |    | use_count      |    | use_count      |
        |----------------|    |----------------|    |----------------|
        | *load_binary() |    | *load_binary() |    | *load_binary() |
        |----------------|    |----------------|    |----------------|
        | *load_shlib()  |    | *load_shlib()  |    | *load_shlib()  |
        |----------------|    |----------------|    |----------------|
        | *core_dump()   |    | *core_dump()   |    | *core_dump()   |
        +----------------+    +----------------+    +----------------+
</verb>
</#if>
<p>図表(4.3) 登録されたバイナリフォーマット


<!--
As with file systems, the binary formats supported by Linux are either built 
into the kernel at kernel build time or available to be loaded as modules. The
kernel keeps a list of supported binary formats (see figure  4.3) and when an 
attempt is made to execute a file, each binary format is tried in turn until 
one works. 
Commonly supported Linux binary formats are a.out and ELF. Executable files
do not have to be read completely into memory, a technique known as demand
loading is used. As each part of the executable image is used by a process it 
is brought into memory. Unused parts of the image may be discarded from 
memory. 
-->
<p>ファイルシステムの場合と同様に、Linux でサポートされているバイナリ
フォーマットは、カーネルをビルドする際にカーネルに組み込まれるか、ローダブル
モジュールとして利用可能かのいずれかである。カーネルはサポートするバイナリ
フォーマットのリストを保持しており(図表(4.3)参照)、ファイルが実行されるときは、
その実行に成功するまで、個々のバイナリフォーマットが順番に試される。
<newline>[see: do_execve(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/fs/exec.c" 
name="fs/exec.c">]<newline>
広くサポートされている Linux のバイナリフォーマットは、<tt>a.out</tt> と
 ELF である。実行ファイルは、完全にメモリに読み込まれる必要はなく、デマンド
ローディングと呼ばれるテクニックが使用される。実行イメージの一部がプロセスに
よって使用されるたびに、その部分だけがメモリに取り込まれる。そのイメージの
使用されない部分は、メモリから破棄されてもよい。

<!--4.8.1  ELF-->
<sect2>ELF

<!--
The ELF (Executable and Linkable Format) object file format, designed by the
Unix System Laboratories, is now firmly established as the most commonly used
format in Linux. Whilst there is a slight performance overhead when compared
with other object file formats such as ECOFF and a.out, ELF is felt to be more
flexible. ELF executable files contain executable code, sometimes refered to as
text, and data. Tables within the executable image describe how the program
should be placed into the process's virtual memory. Statically linked images 
are built by the linker (ld), or link editor, into one single image containing
all of the code and data needed to run this image. The image also specifies 
the layout in memory of this image and the address in the image of the first 
code to execute. 
-->
<p>ELF (Executable and Linkable Format) というオブジェクトファイルのフォー
マットは、Unix System 研究所で設計されたもので、今日では Linux 上で最も広く
利用されているフォーマットとしてその地位が確立している。ECOFF や a.out 
のような他のオブジェクトファイルのフォーマットと比較するとパフォーマンス上
ややオーバーヘッドがあるのだが、ELF はむしろそれら以上に柔軟である点が評価され
ている。
ELF の実行ファイルには、時にはテキスト(text)とも呼ばれる実行コード、および
データが含まれる。実行ファイル内のテーブルでは、そのプログラムがプロセッサの
仮想メモリに置かれる際の方法が示されている。静的にリンクされたイメージは、
リンカ(<tt>ld</tt>)、もしくはリンクエディタによって、そのイメージの実行に必要
なすべてのコードとデータを含む単一のイメージにビルドされる。そのイメージは、
自分自身のメモリ内でのレイアウトや、イメージ内の最初の実行コードのアドレスに
ついても指定している。

<!--                Figure 4.4: ELF Executable File Format-->
<#if output="html">
<figure><ph vspace="1" ><img src="./The-Linux-Kernel-images/figure4-4.gif">
</figure>
</#if>
<#unless output="html">
<verb>
             ELF 実行イメージ
            +---------------+                 
            |  e_ident      |'E' 'L' 'F'
            |  e_entry      | 0x8048090
            |  e_phoff      | 52
            |  e_phentsize  | 32
            |  e_phnum      | 2
            |---------------|
            |               |
            |---------------|
            |  p_type       | PT_LOAD
            |  p_offset     | 0
物理ヘッダ  |  p_vaddr      | 0x8048000
            |  p_filesz     | 68532
            |  p_memsz      | 68532
            |  p_flags      | PF_R, PF_X
            |---------------|
            |  p_type       | PT_LOAD
            |  p_offset     | 68536
            |  p_vaddr      | 0x8059BB8
物理ヘッダ  |  p_filesz     | 2200
            |  p_memsz      | 4248
            |  p_flags      | PF_R, PF_W
            |---------------|
            ~               ~
            ~               ~
            |               |
            |    Code       |
            |               |
            |---------------|
            |               |
            |    Data       |
            |               |
            |               |
            +---------------+
</verb>
</#if>
<p>図表(4.4) ELF 実行ファイルフォーマット


<!--
Figure  4.4 shows the layout of a statically linked ELF executable image. 
It is a simple C program that prints ``hello world'' and then exits. The header
describes it as an ELF image with two physical headers (e_phnum is 2) starting
52 bytes (e_phoff) from the start of the image file. The first physical header
describes the executable code in the image. It goes at virtual address 
0x8048000 and there is 65532 bytes of it. This is because it is a statically 
linked image which contains all of the library code for the printf() call to 
output ``hello world''. The entry point for the image, the first instruction 
for the program, is not at the start of the image but at virtual address 
0x8048090 (e_entry). The code starts immediately after the second physical 
header. This physical header describes the data for the program and is to be 
loaded into virtual memory at address 0x8059BB8. This data is both readable 
and writeable. You will notice that the size of the data in the file is 2200 
bytes (p_filesz) whereas its size in memory is 4248 bytes. This because the 
first 2200 bytes contain pre-initialized data and the next 2048 bytes contain 
data that will be initialized by the executing code. 
-->
<p>
図表(4.4) は、静的にリンクされた ELF 実行イメージのレイアウトを示している。
<newline>[see: <htmlurl 
url="./The-Linux-Kernel-images/linux/include/linux/elf.h" 
name="include/linux/elf.h">]<newline>
これは、簡単な C プログラムであり、"<tt>hello world</tt>" を表示して、終了する
ものである。ヘッダは、ファイルが ELF イメージであること示すのに、2 つの物理
ヘッダを使っていて(<tt>e_phnum</tt> は 2 である)、それらはイメージファイルの
先頭から 52 バイト目(<tt>e_phoff</tt>)から始まっている。
最初の物理ヘッダは、イメージ内の実行コードについて記述している。実行コード
は、仮想アドレスの 0x8048000 に置かれ、その容量が 65532 バイトであることを
示している。この容量は、それが静的にリンクされたイメージだからであり、"<tt>
hello world</tt>" を出力するための <tt>printf()</tt> 呼び出しのライブラリ
コードのすべてを含むからである。イメージのエントリーポイント、すなわちプログ
ラムの最初の命令がある場所は、イメージの先頭ではなく、仮想アドレス 0x8048090 
(<tt>e_entry</tt>) である。
このコードは、二つ目の物理ヘッダのすぐ後ろから始まっている。二つ目の物理ヘッダ
は、プログラムのデータを記述していて、仮想メモリ内のアドレス 0x8059BB8 にロー
ドされるようになっている。このデータは読み書き可能である。ファイルのデータ
サイズが 2200 バイト (<tt>p_filesz</tt>) となっており、メモリ内でのそのサイズ
は 4248 バイトであることに気付いたと思う。これは、最初の 2200 バイトにはあらか
じめ初期化されたデータが含まれていて、次の 2048 バイトには実行コードによって
初期化されるデータが含まれているからである。

<!--
When Linux loads an ELF executable image into the process's virtual address
space, it does not actually load the image. 
It sets up the virtual memory data structures, the process's vm_area_struct
tree and its page tables. When the program is executed page faults will cause 
the program's code and data to be fetched into physical memory. Unused 
portions of the program will never be loaded into memory. Once the ELF binary 
format loader is satisfied that the image is a valid ELF executable image it 
flushes the process's current executable image from its virtual memory. As 
this process is a cloned image (all processes are) this, old, image is the 
program that the parent process was executing, for example the command 
interpreter shell such as bash. This flushing of the old executable image 
discards the old virtual memory data structures and resets the process's page 
tables. It also clears away any signal handlers that were set up and closes 
any files that are open. At the end of the flush the process is ready for the 
new executable image. No matter what format the executable image is, the same 
information gets set up in the process's mm_struct. There are pointers to the 
start and end of the image's code and data. These values are found as the ELF 
executable images physical headers are read and the sections of the program 
that they describe are mapped into the process's virtual address space. That 
is also when the vm_area_struct data structures are set up and the process's 
page tables are modified. The mm_struct data structure also contains pointers 
to the parameters to be passed to the program and to this process's 
environment variables. 
-->
<p>
Linux が ELF 実行イメージをプロセスの仮想アドレス空間にロードするとき、
Linux は実際にそのイメージをロードするわけではない。
<newline>[see: do_load_elf_binary(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/fs/binfmt_elf.c" 
name="fs/binfmt_elf.c">]<newline>
仮想メモリのデータ構造と
プロセスの <tt><ref id="vm_area_struct" name="vm_area_struct"></tt> ツリー、
およびそのページテーブルを設定するだけである。プログラムが実行されると、
ページフォルトによりプログラムのコードとデータが物理メモリに取り出される。
プログラムの使用されていない部分は決してメモリにロードされない。
ELF バイナリフォーマットローダ(loader)は、ロードすべきイメージが有効な ELF 
実行イメージであることを確認すると、そのプロセスの現在の実行イメージをその
仮想メモリから消去する。このプロセスはクローニングされたイメージなので
(すべてのプロセスがそうである)、この古いイメージは、親プロセスが実行している
プログラム、たとえばコマンドインタープリタシェルである <tt>bash</tt> 等のプログ
ラムにすぎないからである。古い実行イメージをこのように消去することで、古い仮想
メモリのデータ構造が破棄され、プロセスのページテーブルがリセットされる。
ローダはまた、設定されたすべてのシグナルハンドラをクリアし、オープンされていた
すべてのファイルを閉じる。それらの消去が終わると、子プロセスは新しい実行
イメージを受け入れ可能になる。
実行イメージのフォーマットが何であれ、同じ情報がプロセスの <tt>
<ref id="mm_struct" name="mm_struct"></tt> に設定される。<tt>mm_struct</tt> 
構造体にはイメージのコードとデータの始点と終点についてのポインタが存在する。
それらの値が見いだされるのは、ELF 実行イメージの物理ヘッダが読み込まれて、
それらのヘッダが記述するプログラムのセクションがプロセスの仮想アドレス空間に
マップされたときである。それは、同時に <tt>vm_area_struct</tt> データ構造体が
設定され、プロセスのページテーブルが変更されるときでもある。<tt>mm_struct
</tt> データ構造体には、そのプログラムに渡されるパラメータとプロセスの環境変
数に対するポインタも含まれている。

<!--ELF Shared Libraries-->
<sect3>ELF 共有ライブラリ

<!--
A dynamically linked image, on the other hand, does not contain all of the 
code and data required to run. Some of it is held in shared libraries that are
linked into the image at run time. The ELF shared library's tables are also 
used by the dynamic linker when the shared library is linked into the image at
run time. Linux uses several dynamic linkers, ld.so.1, libc.so.1 and 
ld-linux.so.1, all to be found in /lib. The libraries contain commonly used 
code such as language subroutines. Without dynamic linking, all programs would
need their own copy of the these libraries and would need far more disk space 
and virtual memory. In dynamic linking, information is included in the ELF 
image's tables for every library routine referenced. The information indicates
to the dynamic linker how to locate the library routine and link it into the 
program's address space. 
-->
<p>反対に、動的にリンクされたイメージは、実行に必要なすべてのコードとデータを
含むわけではない。その幾分かは、共有ライブラリに保持されており、実行時に
イメージにリンクされる。ELF 共有ライブラリのテーブルは、共有ライブラリが実行時
にイメージにリンクされるときに、ダイナミックリンカ(dynamic linker)によっても
使用される。
Linux は、<tt>ld.so.1, libc.so.1, ld-linux.so.1</tt> などいくつかのダイナミック
リンカを使用しており、それらは <tt>/lib</tt> に置かれている。ライブラリには、
言語のサブルーチンなどのよく使用されるコードが含まれている。ダイナミックリンカ
がないと、すべてのプログラムはこれらのライブラリのコピーを自分で所有しなければ
ならず、今よりもかなり多くのディスク容量と仮想メモリを要することになってしま
う。
ダイナミックリンクが使用される場合、参照されるすべてのライブラリルーチンに関
する情報が ELF のイメージテーブルに含まれている。その情報は、ダイナミック
リンカに対して、ライブラリルーチンを探すべき場所とプログラムのアドレス空間に
それをリンクする方法と指示するものである。

<!--
REVIEW NOTE: Do I need more detail here, worked example? 
-->
<p>REVIEW NOTE: 実行時の動作などを、もっと詳しく説明すべきだろうか？

<!--4.8.2  Script Files-->
<sect2>スクリプトファイル

<!--
Script files are executables that need an interpreter to run them. There are a
wide variety of interpreters available for Linux; for example wish, perl and 
command shells such as tcsh. Linux uses the standard Unux TM convention of 
having the first line of a script file contain the name of the interpreter. 
So, a typical script file would start: 
-->
<p>スクリプトファイルは、その実行にインタープリタを必要とする実行ファイル
である。Linux 上で入手可能なインタープリタは非常に多種類ある。たとえば、<tt>
wish, perl</tt>, それに <tt>bash</tt> のようなコマンドシェルである。Linux で
は、標準的な Unix の慣習に従って、スクリプトファイルの最初の一行にインタープリ
タの名前を書くようになっている。典型的なスクリプトファイルは次にように始まる。

<verb>
#!/usr/bin/wish
</verb>

<!--
The script binary loader tries to find the intepreter for the script. 
It does this by attempting to open the executable file that is named in the 
first line of the script. If it can open it, it has a pointer to its VFS inode
and it can go ahead and have it interpret the script file. The name of the 
script file becomes argument zero (the first argument) and all of the other 
arguments move up one place (the  original first argument becomes the new 
second argument and so on). Loading the interpreter is done in the same way as
Linux loads all of its executable files. Linux tries each binary format in 
turn until one works. This means that you could in theory stack several 
interpreters and binary formats making the Linux binary format handler a very 
flexible piece of software. 
-->
<p>スクリプトのバイナリーローダは、そのスクリプトのインタープリタを探そうとす
る。
<newline>[see: do_load_script(), in <htmlurl 
url="./The-Linux-Kernel-images/linux/fs/binfmt_script.c" 
name="fs/binfmt_script.c">]<newline>
そのためにローダは、スクリプトの最初の行で指名されている実行ファイルを
オープンしてみる。オープンできたなら、そのインタープリタは、オープンした
ファイルの VFS inode に対するポインタを所持し、さらに先を読み込んで、
スクリプトファイルを解釈する。スクリプトファイルの名前は、引数 0 (最初の
引数)となり、他のすべての引数の番号がひとつずつ上がる(すなわち、もともと最初に
あった引数は新たに第二引数となり、以下それに続く)。インタープリタのロードは、
Linux が他の実行ファイルをロードする方法と同じである。Linux は、実行に成功する
まで、個々のバイナリフォーマットを順番に試す。つまり、理論的には、いくつかの
インタープリタとバイナリフォーマットを用意しておいて、Linux のバイナリ
フォーマットハンドラを非常に柔軟なソフトウェアにすることが可能なのである。


<!--
Footnotes:

1 REVIEW NOTE: I left out SWAPPING because it does not appear to be used. 

2 Think of a nut the kernel is the edible bit in the middle and the shell goes
around it, providing an interface. 
-->
<p>
<label id="chapter_p_fn1">
<footnote>
(脚注1)REVIEW NOTE: スワッピング(SWAPPING)状態はわざと省いた。使われている
とは思えないからだ。<newline>
(脚注2)木の実に例えると、カーネルは中心の食べられる部分であり、シェルが
その周りを囲んで、インターフェイスを提供している。
</footnote>