12

我不明白为什么 Unix 必须fork()创建一个新进程。在 Win32 API 中,我们CreateProcess()创建了一个新进程并将可执行文件加载到其地址空间中,然后从入口点开始执行。但是 Unix 提供了用于创建新进程的 fork,我不明白如果我想运行另一个进程,为什么要复制我的进程。

所以让我问这两个问题:

  1. 如果fork()and thenexec()更有效,为什么没有函数,因为我们几乎在每种情况下forkexec(const char *newProc)都会调用exec()after ?fork()
  2. 如果它不是更有效,那为什么还fork()存在呢?
4

3 回答 3

13

fork()通话就足够了。它也更灵活;它允许您调整子进程中的 I/O 重定向等操作,而不是使创建进程的系统调用复杂化。使用 SUID 或 SGID 程序,它允许子进程在执行其他进程之前失去其提升的特权。

如果您想要一种复杂的方式来创建流程,请查找该posix_spawn()函数。

#include <spawn.h>

int posix_spawn(pid_t *restrict pid, const char *restrict path,
        const posix_spawn_file_actions_t *file_actions,
        const posix_spawnattr_t *restrict attrp,
        char *const argv[restrict], char *const envp[restrict]);

int posix_spawnp(pid_t *restrict pid, const char *restrict file,
          const posix_spawn_file_actions_t *file_actions,
       const posix_spawnattr_t *restrict attrp,
       char *const argv[restrict], char *const envp[restrict]);

不同之处在于posix_spawnp()在 PATH 上搜索可执行文件。

还有一整套用于处理posix_spawn_file_actions_tposix_spawnattr_t类型的其他函数(按照参考手册页底部的“另见”链接)。

这更像是CreateProcess()在 Windows 上。不过,在大多数情况下,使用fork()后跟使用exec()更简单。


我不明白你的意思。子进程代码将由我编写,那么编写if (fork() == 0)此代码与将这段代码放在 child's 的开头有什么区别main()

很多时候,您执行的代码不是您编写的,因此您无法修改子进程开始时发生的情况。想想贝壳;如果您从 shell 运行的唯一程序是您编写的程序,那么生活将变得非常贫困。

很多时候,您执行的代码会从许多不同的地方调用。特别是,考虑一个 shell 和一个程序,它们有时会在管道中执行,有时会在没有管道的情况下执行。被调用的程序不能告诉它应该做什么 I/O 重定向和修复;调用程序知道。

如果调用程序以提升的权限(SUID 或 SGID 权限)运行,则通常希望在运行另一个程序之前关闭这些权限。依靠其他程序知道该怎么做是......愚蠢的。

于 2011-10-15T19:48:42.493 回答
3

类 UNIX 操作系统(至少是较新的 Linux 和 BSD 内核)通常具有非常高效 fork的实现——它“非常便宜”,以至于在某些语言中有基于它的“线程”实现。

最后,forkexec函数是 ~n - 对于 n 的一些小值 - 应用程序代码行。

我当然希望windows有这么有用ForkProcess:(

快乐编码。


一位 cnicutar 提到,Copy-On-Write (COW)是使用的一种策略。

于 2011-10-15T19:47:29.063 回答
0

有一个相当于forkexec的函数——system

http://www.tutorialspoint.com/c_standard_library/c_function_system.htm

#include <stdio.h>
#include <string.h>

int main ()
{
  char command[50];

  strcpy( command, "ls -l" );
  system(command);

  return(0);
} 
于 2015-03-23T14:34:09.960 回答