forking()和CreateProcess()

时间:2012-12-12 12:35:53

标签: fork createprocess

forking()和CreateProcess(包含所有必需的参数),Linux和WinXP分别是一样的吗?

如果它们不同,那么有人可以解释两种情况中每种情况的差异吗?

由于

3 个答案:

答案 0 :(得分:5)

他们在不同的系统上做不同的事情。 CreateProcess是仅限Windows的功能,而fork仅适用于POSIX(例如Linux和Mac OSX)系统。

fork系统调用创建一个新进程,并在调用fork函数的位置继续执行父进程和子进程。 CreateProcess创建一个新进程并从磁盘加载程序。唯一的相似之处是最终结果是创建了一个新流程。

有关详情,请参阅CreateProcessfork上的相应手册页。

答案 1 :(得分: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会复制并返回两个值。我们调用了复制的进程父进程和另一个子进程。如果我们调用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()。实际上,fork()与Windows中的CreateThread()更相似。

答案 2 :(得分:1)

CreateProcess采取以下步骤:

  • 在内核中创建并初始化过程控制块(PCB)。
  • 创建并初始化新的地址空间。
  • 将程序prog加载到地址空间中。
  • 将参数args复制到地址空间中的内存中。
  • 初始化硬件上下文以在“开始”处开始执行。
  • 通知调度程序新过程已准备就绪。

Unix的fork执行以下步骤:

  • 在内核中创建并初始化过程控制块(PCB)
  • 创建一个新的地址空间
  • 使用以下所有内容的副本来初始化地址空间 父级的地址空间
  • 继承父级的执行上下文(例如,任何打开的文件)
  • 通知调度程序新流程已准备好运行

它将创建父进程的完整副本,并且父进程不会为子进程设置运行时环境,因为父进程会信任自己的设置。子进程是父进程的完整副本,但其进程ID(fork返回的内容)除外。分叉的进程将继续与其父进程运行相同的程序,直到执行显式的exec。当子进程调用exec which时,新的可执行映像将进入内存并运行。

制作完整副本的效率如何?写时复制。它实际上仅复制虚拟内存映射。段表中的所有段均为只读。如果父级或子级编辑段中的数据,则会引发异常,并且内核会创建该段的完整内存副本。 answer

中对此进行了很好的解释

父母与孩子之间共享资源有几个好处:  -直观地进行资源管理:维护进程状态所需的内存更少  -共享缓存资源意味着在不覆盖数据时,数据具有更大的时间局部性,从而提高了性能,因为从较大的缓存/磁盘中检索数据非常耗时。

共享资源的缺点:  -当写操作很常见时,它将数据置于其他进程的无效状态,这会导致一致性丢失,如果子进程在单独的内核上运行,则代价很高,因为更改必须传播到L3缓存。

尽管如此,一般而言,程序读取的内容要比写入的内容多得多,通常,子级/父级只需要对其堆栈进行写入操作,这只是其程序块的一小部分。

另外,Unix fork是不同的,因为它返回两次,一次返回父进程(其子进程的进程ID),一次返回子进程(0,表示您是一个新的子进程),这就是我们在我们的系统中的区别代码是我们是孩子还是父母。

Unix Exec执行以下操作:

  • 将程序prog加载到当前地址空间中。
  • 将参数args复制到地址空间中的内存中。
  • 初始化硬件上下文以从“开始”开始执行。

父母可以选择等待孩子完成。当孩子结束时,通知出口的时间是通知父母的等待时间。