forking()とCreateProcess(必要なすべての引数を含む)は、それぞれLinuxとWinXPで同じものですか?
それらが異なる場合、誰かが2つのケースのそれぞれで何が起こるかという観点から違いを説明できますか?
ありがとう
forking()とCreateProcess(必要なすべての引数を含む)は、それぞれLinuxとWinXPで同じものですか?
それらが異なる場合、誰かが2つのケースのそれぞれで何が起こるかという観点から違いを説明できますか?
ありがとう
彼らは異なることを、そして異なるシステムで行います。CreateProcess
はWindowsのみの機能ですfork
が、POSIX(LinuxやMac OSXなど)システムでのみ機能します。
システムコールは新しいプロセスを作成し、関数が呼び出されfork
た時点から親と子の両方で実行を継続します。新しいプロセスを作成し、ディスクからプログラムをロードします。唯一の類似点は、最終結果が新しいプロセスが作成されることです。fork
CreateProcess
詳細については、およびのそれぞれのマニュアルページを参照しCreateProcess
てくださいfork
。
CreateProcessは、次の手順を実行します。
Unixのフォークは次の手順を実行します。
親プロセスの完全なコピーが作成され、親プロセスは自身の設定を信頼するため、親は子のランタイム環境を設定しません。子は、プロセスID(forkが返すもの)を除いて、親の完全なコピーです。フォークされたプロセスは、明示的なexecを実行するまで、親と同じプログラムを実行し続けます。子がexecwhichを呼び出すと、新しい実行可能イメージがメモリに読み込まれ、実行されます。
完全なコピーを作成するのはどのように効率的ですか?コピーオンライト。実際には、仮想メモリマップをコピーするだけです。セグメントテーブルのすべてのセグメントは読み取り専用です。親または子がセグメント内のデータを編集すると、例外がスローされ、カーネルはその完全なメモリコピーを作成します。これはこの答えでうまく説明されています
親と子の間でリソースを共有することには、いくつかの利点があります。-直感的に、リソース管理:プロセスの状態を維持するために必要なメモリが少なくて済みます-キャッシュリソースが共有されると、データが上書きされていないときにデータの時間的局所性が高まり、パフォーマンスが向上しますより大きなキャッシュ/ディスクからデータを取得するには時間がかかるためです。
共有リソースのデメリット:-書き込みが一般的である場合、他のプロセスではデータが無効な状態になります。これにより、コヒーレンシミスが発生し、子プロセスが別のコアで実行されている場合、変更が必要になるため、コストがかかります。 L3キャッシュまで伝播します。
ただし、一般的に、プログラムは書き込みよりもはるかに多くの情報を読み取ります。通常、子/親はスタックに書き込みを行うだけでよく、それはプログラムブロックのごく一部です。
さらに、Unix forkは、親(子のプロセスID)で1回、子(0、新しい赤ちゃんプロセスであることを祝福します)で1回、2回返されるという点で異なります。これは、コードで区別する方法です。子または親です。
UnixExecは次のことを行います。
親には、子が終了するのを待つオプションがあります。子が終了したとき、exitが呼び出されたときは、親の待機が通知されたときです。
違いを示すために2つの例を示します
fork()
::
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int fac(int);
int main(void)
{
int child_ret,input_num=-1;
pid_t pid1;
while(input_num<0){
printf("\nPlease input a non-negative number: ");
scanf("%d",&input_num);
}
if((pid1=fork())<0){
printf("fork error");
}
else if(pid1==0){
printf("\nI am the child process,my PID is %d.\n\nThe first %d numbers of fibonacci sequence is:\n", getpid(),input_num);
for (int i=0;i<input_num;i++)
{printf("%d\n", fac(i+1));}
}
else{
wait(&child_ret);
printf("\nI am the parent process,my PID is %d.\n\n", getpid());
}
return 0;
}
int fac(int n)
{
if (n<=2) return n-1;
else
{
return fac(n-1)+fac(n-2);
}
}
このプログラムでは、forkがコピーを実行して2つの値を返します。コピーしたプロセスを親プロセスと他の1つの子プロセスを呼び出しました。exec()関数を呼び出すと、プロセス全体がPIDを除く新しいプログラムに置き換えられます。
CreateProcess()
:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( VOID )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPTSTR szCmdline=_tcsdup(TEXT("MyChildProcess"));
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
szCmdline, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d)./n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
これはMSDNの例です。新しいプロセスを作成するために呼び出すものは、Windowsシステムの別個の*.exeプログラムである必要があります。新しいプロセスはまったく新しいプロセスであり、戻り値と古いプロセスとの唯一のつながりがあります。
結論として、私たちはしばしばfork()+exec()
として見ますCreateProcess()
。実際、 Windowsの場合fork()
とより似てCreateThread()
います。