In *nix systems, processes are created by using fork() system call. Consider for example, init process creates another process.. First it forks itself and creates the a process which has the context like init. Only on calling exec(), this child process turns out to be a new process. So why is the intermediate step ( of creating a child with same context as parent ) needed? Isn't that a waste of time and resource, because we are creating a context ( consumes time and wastes memory ) and then over writing it?
为什么这没有实现为分配一个空的内存区域然后调用 exec()?这样可以节省时间和资源,对吗?
中间步骤使您能够在子进程中设置共享资源,而外部程序不会意识到这一点。典型的例子是构造一个管道:
\n\n// read output of "ls"\n// (error checking omitted for brevity)\nint pipe_fd[2];\npipe(&pipe_fd);\nif (fork() == 0) { // child:\n close(pipe_fd[0]); // we don\'t want to read from the pipe\n dup2(pipe_fd[1], 1); // redirect stdout to the write end of the pipe\n execlp("ls", "ls", (char *) NULL);\n _exit(127); // in case exec fails\n}\n// parent:\nclose(pipe_fd[1]);\nfp = fdopen(pipe_fd[0], "r");\nwhile (!feof(fp)) {\n char line[256];\n fgets(line, sizeof line, fp);\n ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n请注意标准输出到管道的重定向是如何在子进程中、在fork
和之间完成的exec
。当然,对于这个简单的情况,可能有一个生成 API,它可以在给定正确的参数的情况下自动执行此操作。但该fork()
设计允许对子 \xe2\x80\x94 中的每进程资源进行任意操作,可以关闭不需要的文件描述符、修改每进程限制、删除特权、操作信号掩码等。如果没有fork()
,用于生成进程的 API 最终会变得非常臃肿或不太有用。事实上,竞争操作系统的进程生成调用通常介于两者之间。
至于内存的浪费,可以通过写时复制技术来避免。fork()
不会为子进程分配新内存,而是将子进程指向父进程的内存,并指示仅当页面被写入时才复制该页面。这fork()
不仅提高了内存效率,而且速度也很快,因为它只需要复制一个“目录”。