出典(authority):フリー百科事典『ウィキペディア(Wikipedia)』「2017/01/30 16:10:03」(JST)
「Fork」のその他の用法については「フォーク」をご覧ください。 |
fork(フォーク)とは、プロセスのコピーを生成するものである。UNIXおよびUnix系OSではシステムコールのひとつで、新たに作り出されたプロセスを子プロセス、fork()
を呼び出したプロセスを親プロセスと呼び、fork()システムコールの戻り値によって親と子の処理を区別する。子プロセスではfork()の戻り値は0であり、親プロセスの戻り値は新たに生成された子プロセスのプロセス識別子、エラーが起きた場合は-1である。また、マルチスレッド環境でスレッドのコピーを作ることもforkと呼ぶことがある。
forkが呼び出されると、子プロセスのためのアドレス空間が新たに作成される。子プロセスのアドレス空間には親プロセスが持っていた全セグメントのコピーがあるが、コピーオンライト機能によって実際の物理メモリの確保は遅延される(すなわち、一時的に同じ物理メモリセグメント群を親子で共有する)。親プロセスと子プロセスは同じコードセグメントを持つが、独立して実行される。
Unixにとってforkは重要であり、フィルタの開発を奨励している設計哲学の重要な部分を担っている。Unixでのフィルタは標準入力を入力とし標準出力を出力とする(通常小さな)プログラムである。シェルがフィルタをパイプで連結することで、複雑な処理を実現できる。例えば次のようにfind(1)
コマンドの出力をwc(1)
コマンドの入力に連結すると、拡張子が ".cpp" のファイルをカレントディレクトリ配下で探し、見つかったファイル数を表示できる。
$ find . -name "*.cpp" -print | wc -l
このコマンド行を入力すると、シェルは自分自身をforkし、プロセス間通信の1つであるパイプを使って find
コマンドの出力を wc
コマンドの入力に結びつける。パイプは2つの新たなファイル識別子を生成し、2つの子プロセスを生成する(それぞれ find
と wc
に対応)。2つの子プロセスはまず dup2(2)
で対応するパイプのファイル識別子を複製して標準入力と標準出力に置き換える。そしてそれぞれの子プロセスがexec(3)
ファミリのシステムコールを使って、実行すべきコマンドのプログラムで自身をオーバーレイする。
より一般的に、シェルはユーザーがコマンド行を入力するたびにforkを行っている。子プロセスはシェルがforkを行うことで生成され、子プロセスがexec
でオーバーレイを行い、実行すべきプログラムのコードをマッピングする。
実行ファイルを実行しようとすると、プロセスが生成される。実行ファイルはセグメントと呼ばれるブロックにグループ化されたバイナリコードを含んでいる。各セグメントは特定の種類のデータを格納するのに使われる。典型的なELF形式の実行ファイルには、以下のようなセグメントが存在する。
readelf
コマンドを使えば、ELF形式のファイルの詳細を表示できる。そのようなファイルを実行するためにメモリ上にロードすると、セグメント群がメモリにロードされることになる。実行ファイル全体を連続なメモリ位置にロードする必要はない。メモリはページと呼ばれる同じ大きさ(通常4KB)の部分に分けられている。したがって実行ファイルをメモリにロードする際、実行ファイル内のそれぞれの位置がそれぞれ異なるページに置かれる(ページ群は連続とは限らない)。大きさが10KBのELF形式の実行ファイルがあるとする。そのOSのサポートするページサイズが4KBなら、そのファイルは4KB、4KB、2KBという3つの部分に分けてロードされる(他にコールスタックも必要)。この3つのフレームはメモリ中の任意のフリーなページに置くことができる[1]。
fork()
システムコールを実行すると、本来ならばOSが子プロセスのために親プロセスの持つ全ページを物理メモリ上の別の位置にコピーすることになる。しかし、場合によってはその必要はない。子プロセスがfork()
直後に "exec
" システムコール(実行ファイルを実行するときに使用する)を実行する場合や終了する場合である。親プロセスが何らかのコマンドを実行するためだけに子プロセスを生成した場合、子プロセスのアドレス空間は実行すべきコマンドですぐに置換されるので、親プロセスのページ群をコピーする必要はない。
そのため、コピーオンライト (COW) という技法が使われる。COWでは、fork時に親プロセスのページ群を子プロセスにコピーしない。その代わりページ群は親プロセスと子プロセスの間で共有される。親子いずれかのプロセスがページの内容を更新しようとしたとき、そのページだけコピーを作成し、書き込もうとしたプロセスの当該ページだけが更新される。書き込んだプロセスはその後その新たにコピーしたページを使用する。もう一方のプロセス(共有ページに書き込まなかったプロセス)は、コピー元のページを使用し続ける(共有状態は解消される)。何らかのプロセスが書き込もうとしたときにページがコピーされるので、この技法をコピーオンライトと呼ぶ。
vfork
はもう1つのプロセス生成用UNIXシステムコールである。vfork()
システムコールで子プロセスを生成すると、子プロセスが終了するかexecve()
ファミリのシステムコールで新たな実行イメージに切り換えるまでそのシステムコールの延長上で親プロセスが待ち合わせる。vfork
でも親プロセスと子プロセスでページ群を共有するが、コピーオンライトは必要としない。子プロセスが共有ページに更新を加えてもコピーは作成せず、親プロセスからもその更新が見える。ページを全くコピーしないので、子プロセスでコマンドを実行する場合には非常に効率的である。
実装によっては vfork()
は fork()
と同じである[2]。
vfork()
とfork()
の唯一の違いは、親プロセスと子プロセスがコードとデータを共有できる点である。これによって複製は劇的に高速化されるが、使い方を誤ると親プロセスの一貫性が壊れる危険性がある。
直後に exec
または _exit()
を呼び出す以外のvfork()
の使用は推奨されない。特にLinuxのmanページではvforkそのものの使用が推奨されていない[3]。
Linuxが過去からこの幽霊を蘇らせたことはやや不幸である。BSDのmanページには「このシステムコールは妥当なシステム共有機構が実装された場合には削除される。ユーザは vfork() のメモリ共有機能に依存するべきではない。何故ならば、このシステムコールが削除された場合には、それは fork(2) の同義語とされるからである」と記されている。
vfork()
で生成した子プロセスがvfork()
を呼び出したルーチンからさらに外側に復帰した場合、親プロセスのコールスタックを書き変えてしまうので、vfork()
から親プロセスが戻ったときの動作を保証できない。また、execせずに子プロセスを終了する場合、_exit()
ではなくexit()
を使用すると、標準I/Oチャネルをフラッシュしてクローズするため親プロセスの標準I/O構造にダメージを与える危険性がある。なお、fork()
の場合でも子プロセスがexit()
を呼び出すのは危険である。
vfork()
後に子プロセスでシグナルハンドラが呼び出された場合、子プロセスの他のコードと同じ規則に従う必要がある[2]。
組み込みシステムではメモリ管理ユニット (MMU) が存在しない場合があり、fork()
でのコピーオンライトの実装ができないことがある。システムがプロセス毎のアドレス空間を他の何らかの機構で(例えばセグメント方式で)サポートする場合、プロセスの使用する全メモリをコピーすれば実質的には同じである。しかしそれは非常に時間がかかるし、多くの場合すぐに別の実行ファイルのイメージで書き換えられるので無駄である。
全プロセスが単一のアドレス空間を共有している場合、例えば全メモリページをスワップしてコンテキストスイッチするというfork()
の実装も考えられる。μClinuxベースのOSなどの組み込みOSが採用しているのは、fork()
を廃して vfork()
だけを実装するという方法である。そのため、forkを使っているところを全てvforkで動作できるように書き換えている。
Unix系やLinuxでのfork機構は、基盤となっているハードウェアにある種の前提を課している。リニアなメモリ空間とページング機構を持ち、連続なアドレス範囲のメモリコピーを効率的に行えるという前提である。VMS(現在のOpenVMS)の当初の設計では、コピー操作後に少数の具体的なアドレスの内容書き換えを行うフォークは危険だとみなされていた。現在のプロセス状態におけるエラーが子プロセスにコピーされるかもしれない。そこでプロセスのスポーン(産卵)というメタファーが使われた。すなわち、新しいプロセスのメモリレイアウトの各コンポーネントを一から新たに構築する。ソフトウェア工学的観点からすれば後者(スポーン)の手法の方がきれいで安全だが、フォークの方が効率的なのでよく使われている。スポーン方式は後にマイクロソフトのOSで採用された。
#include <stdio.h> /* printf, stderr, fprintf */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* _exit, fork */
#include <stdlib.h> /* exit */
#include <errno.h> /* errno */
int main(void)
{
pid_t pid;
/* 子プロセスと親プロセスの両方の出力が
* 標準出力に書かれる。
* 両者は同時に動作する。
*/
pid = fork();
if (pid == -1)
{
/* エラー:
* fork()が-1を返す場合、エラーが起きたことを示す。
* 例えばプロセス数が制限に達した場合など。
*/
fprintf(stderr, "can't fork, error %d\n", errno);
exit(EXIT_FAILURE);
}
if (pid == 0)
{
/* 子プロセス:
* fork()が0を返す場合、子プロセスである。
* 1秒に1ずつ、10まで数える。
*/
int j;
for (j = 0; j < 10; j++)
{
printf("child: %d\n", j);
sleep(1);
}
_exit(0); /* exit() を使わない点に注意 */
}
else
{
/* fork() が正の数を返す場合、親プロセスである。
* その値は生成した子プロセスのPIDである。
* ここでも10まで数える。
*/
int i;
for (i = 0; i < 10; i++)
{
printf("parent: %d\n", i);
sleep(1);
}
exit(0);
}
return 0;
}
#!/usr/bin/env perl -w
use strict;
if (fork) { # 親プロセス
foreach my $i (0 .. 9) {
print "Parent: $i\n";
sleep 1;
}
}
else { # 子プロセス
foreach my $i (0 .. 9) {
print "Child: $i\n";
sleep 1;
}
exit(0); # forkした子プロセスの終了
}
exit(0); # 親プロセスの終了
#!/usr/bin/env python
import os, time, sys
def createDaemon():
"This function create a service/Daemon that will execute a det. task"
try:
# forkしたPIDを格納
pid = os.fork()
if pid > 0:
print 'PID: %d' % pid
sys.exit()
except OSError as error:
print 'Unable to fork. Error: %d (%s)' % (error.errno, error.strerror)
sys.exit(1)
doTask()
def doTask():
"This function create a task that will be a daemon"
# ライトモードでファイルをオープン
log_file = open('/tmp/tarefa.log', 'w')
while True:
print >> log_file, time.ctime()
log_file.flush()
time.sleep(2)
# ファイルをクローズ
log_file.close()
if __name__ == '__main__':
# デーモンを生成
createDaemon()
Fork-Execは、UNIXで一般的に使われる手法であり、新たなプログラムをプロセスとして実行する。fork()は親プロセスを2つの同一内容のプロセスに(フォークの先のように)分岐させるシステムコールである。fork()によって子プロセスが親プロセスのコピーとして生成され、子プロセスがexec()システムコールを呼び出すことで(子プロセス)自身の内容を置き換える。
親プロセスが子プロセスの終了を待ち合わせる場合、子プロセスの終了コード (exit code) を受け取ることができる。子プロセスがゾンビプロセスとなるのを防ぐには、親プロセスがwait(英語版)システムコールを使用する必要があり、そのタイミングは定期的でもよいし、SIGCHLDシグナルを受け取った際でもよい。
子プロセスがexec()を呼び出すと、そのアドレス空間の内容は全て失われ、指定されたプログラムを実行するためのアドレス空間のマッピングが新しく設定される。これをオーバーレイと呼ぶ。アドレス空間は全て置き換えられるが、オープン済みファイルのファイル記述子群は close-on-exec が指定されたときだけ exec()時に自動的にクローズされる。この特徴を利用して、fork()を呼び出す前にパイプを作成しておき、exec()で指定された新しいプログラムとの通信を行うというUNIX特有の手法が実現されている。
なお、Microsoft Windows では fork() 単独に相当するシステムコールがなく、fork-exec モデルを採用していない。代わりにspawn()(英語版)ファミリ関数が process.h で定義されており、fork-exec に相当する働きをする。
fork(2)
– JM Project Linux System Calls マニュアル
A fork, in cutlery or kitchenware, is a tool in the form of a trident consisting of a handle with several narrow tines on one end. The usually metal utensil is used to lift food to the mouth or to hold ingredients in place while they are being cut by a knife. Food can be lifted either by spearing it on the tines or by holding it on top of the tines, which are often curved slightly.
The early history of the fork is obscure. As a kitchen and dining utensil it is generally believed to have originated in the Roman Empire, as proved by archaeological evidences. The personal table fork most likely originated in the Eastern Roman (or Byzantine) Empire. Its use spread to what is now the Middle East during the first millennium AD and then spread into southern Europe during the second millennium. It did not become common in northern Europe until the 18th century and was not common in North America until the 19th century.
The fork is a primarily Western utensil, whereas in east Asia chopsticks have been more prevalent. Today, forks are increasingly available throughout east Asia.
The word fork comes from the Latin furca, meaning "pitchfork". Some of the earliest known uses of forks with food occurred in Ancient Egypt, where large forks were used as cooking utensils.[1] Bone forks had been found in the burial site of the Bronze Age Qijia culture (2400–1900 BC) as well as later Chinese dynasties' tombs.[2] The Ancient Greeks used the fork as a serving utensil.[3] The Greek name for fork is still used in some European languages, for instance in the Venetian, Greek, and Albanian languages.
In the Roman Empire, bronze and silver forks were used, and indeed many examples are displayed in museums around Europe.[4][5] The use varied according to local customs, social class and the nature of food, but forks of the earlier periods were mostly used as cooking and serving utensils. The personal table fork was most likely invented in the Eastern Roman (Byzantine) Empire, where they were in common use by the 4th century (its origin may even go back to Ancient Greece, before the Roman period).[6][7] Records show that by the 9th century a similar utensil known as a barjyn was in limited use in Persia within some elite circles.[8] By the 10th century, the table fork was in common use throughout the Middle East.[1]
The first recorded introduction of the fork to Europe, as recorded by the theologian and cardinal Peter Damian,[9] was by Theophano Sklereina the Byzantine wife of Holy Roman Emperor Otto II, who nonchalantly wielded one at an Imperial banquet in 972, astonishing her Western hosts.[10] By the 11th century, the table fork had become increasingly prevalent in the Italian peninsula. It gained a following in Italy before any other European region because of historical ties with Byzantium, and continued to gain popularity due to the increasing presence of pasta in the Italian diet.[11] At first, pasta was consumed using a long wooden spike, but this eventually evolved into three spikes, a design better suited to gathering the noodles.[12] In Italy, it became commonplace by the 14th century and was almost universally used by the merchant and upper classes by 1600. It was proper for a guest to arrive with his own fork and spoon enclosed in a box called a cadena; this usage was introduced to the French court with Catherine de' Medici's entourage. In Portugal, forks were first used at the time of Infanta Beatrice, Duchess of Viseu, King Manuel I of Portugal's mother[13] around 1450. However, forks were not commonly used in Southern Europe until the 16th century when they became part of Italian etiquette.[14] The utensil had also gained some currency in Spain by this time,[15] Its use gradually spread to France. Nevertheless, most of Europe did not adopt use of the fork until the 18th century.[6]
Polish deputy minister has said in 2016, that Poland "taught the French how to use a fork".[16] However the truth is less easy, Henri III was the one to actually introduce proper usage of the fork after a travel to Poland, however on the way home he apparently went to Venice to visit his mother homeland and that's where he supposedly discovered the little pitchfork.
Long after the personal table fork had become commonplace in France, at the supper celebrating the marriage of the duc de Chartres to Louis XIV's natural daughter in 1692, the seating was described in the court memoirs of Saint-Simon: "King James having his Queen on his right hand and the King on his left, and each with their cadenas." In Perrault's contemporaneous fairy tale of La Belle au bois dormant (1697), each of the fairies invited for the christening is presented with a splendid "fork holder".
The fork's adoption in northern Europe was slower. Its use was first described in English by Thomas Coryat in a volume of writings on his Italian travels (1611), but for many years it was viewed as an unmanly Italian affectation.[17] Some writers of the Roman Catholic Church expressly disapproved of its use, St. Peter Damian seeing it as "excessive delicacy":[12] It was not until the 18th century that the fork became commonly used in Great Britain,[18] although some sources say that forks were common in France, England and Sweden already by the early 17th century.[19][20][dubious – discuss]
The fork did not become popular in North America until near the time of the American Revolution.[1] The curved fork used in most parts of the world today was developed in Germany in the mid 18th century while the standard four-tine design became current in the early 19th century. The fork was important in Germany because they believed that eating with the fingers was rude and disrespectful. The fork led to family dinners and sit-down meals, which are important features of German culture.[21]
This section contains a list of miscellaneous information. Please relocate any relevant information into other sections or articles. (January 2017) |
Wikimedia Commons has media related to Fork. |
Look up fork in Wiktionary, the free dictionary. |
全文を閲覧するには購読必要です。 To read the full text you will need to subscribe.
拡張検索 | 「hayfork sign」「Bezold-Edelmann continuous range of fork」 |
.