【问题标题】:forking() and CreateProcess()forking() 和 CreateProcess()
【发布时间】:2012-12-12 12:35:52
【问题描述】:

对于 Linux 和 WinXP,forking() 和 CreateProcess(带有所有必需的参数)是否分别相同?

如果它们不同,那么有人可以解释这两种情况的不同之处吗?

谢谢

【问题讨论】:

    标签: fork createprocess


    【解决方案1】:

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

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

    有关更多信息,请阅读CreateProcessfork 上的相应手册页。

    【讨论】:

      【解决方案2】:

      CreateProcess 采取以下步骤:

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

      Unix 的 fork 采取以下步骤:

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

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

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

      很好地解释了这一点

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

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

      不过,一般来说,程序读取的内容远多于写入内容,通常子/父级只需要对其堆栈进行写入,而这只是其程序块的一小部分。

      另外 Unix fork 是不同的,因为它返回两次,一次在父进程中(其子进程的进程 id),一次在子进程中(0,恭喜你是一个新的婴儿进程),这就是我们在我们的如果我们是孩子或父母的代码。

      Unix Exec 执行以下操作:

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

      父母可以选择等待孩子完成。当孩子完成时,当调用退出时是通知父母等待的时间。

      【讨论】:

        【解决方案3】:

        我举两个例子来说明区别:
        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() 更相似。

        【讨论】:

          猜你喜欢
          • 2011-10-26
          • 2023-04-06
          • 2010-09-20
          • 1970-01-01
          • 1970-01-01
          • 2012-05-31
          • 1970-01-01
          • 1970-01-01
          • 2015-06-23
          相关资源
          最近更新 更多