为什么 Unix 有 fork() 而没有 CreateProcess()?

发布于 2024-12-09 22:06:22 字数 686 浏览 0 评论 0原文

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

那么让我问这两个问题:

  1. 如果 fork() 然后 exec() 效率更高,为什么没有一个函数 forkexec(const char * newProc) 因为几乎在所有情况下我们都会在 fork() 之后调用 exec() 吗?
  2. 如果它没有效率更高,为什么还要存在 fork() 呢?

I do not get why Unix has fork() for creating a new process. In Win32 API we have CreateProcess() which creates a new process and loads an executable into its address space, then starts executing from the entry point. However Unix offers fork for creating a new process, and I don't get why would I duplicate my process if I'd like to run another process.

So let me ask these two questions:

  1. If fork() and then exec() is more efficient, why isn't there a function forkexec(const char *newProc) since we will call exec() after fork() almost in every case?
  2. If it is not more efficient, why does fork() exist at all?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如梦亦如幻 2024-12-16 22:06:22

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

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

#include ;

int posix_spawn(pid_t *限制 pid, const char *限制路径,
        const posix_spawn_file_actions_t *file_actions,
        const posix_spawnattr_t *限制 attrp,
        char *const argv[限制]、char *const envp[限制]);

int posix_spawnp(pid_t *限制 pid, const char *限制文件,
          const posix_spawn_file_actions_t *file_actions,
       const posix_spawnattr_t *限制 attrp,
       char *const argv[限制]、char *const envp[限制]);

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

还有一整套其他函数用于处理 posix_spawn_file_actions_t 和 posix_spawnattr_t 类型(请点击引用的手册页底部的“另请参阅”链接)。

这有点像 Windows 上的CreateProcess()。不过,在大多数情况下,使用 fork() 后紧跟着 exec() 会更简单。


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

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

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

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

The fork() call is sufficient. It is also more flexible; it allows you to things like adjust the I/O redirection in the child process, rather than complicating the system call to create the process. With SUID or SGID programs, it allows the child to lose its elevated privileges before executing the other process.

If you want a complex way to create a process, lookup the posix_spawn() function.

#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]);

The difference is the posix_spawnp() does a search on PATH for the executable.

There is a whole set of other functions for handling posix_spawn_file_actions_t and posix_spawnattr_t types (follow the 'See Also' links at the bottom of the referenced man page).

This is quite a bit more like CreateProcess() on Windows. For the most part, though, using fork() followed shortly by exec() is simpler.


I don't understand what you mean. The child process code will be written by me, so what is the difference between writing if (fork() == 0) and putting this code in the beginning of child's main()?

Very often, the code you execute is not written by you, so you can't modify what happens in the beginning of the child's process. Think of a shell; if the only programs you run from the shell are those you've written, life is going to be very impoverished.

Quite often, the code you execute will be called from many different places. In particular, think of a shell and a program that will sometimes be executed in a pipeline and sometimes executed without pipes. The called program cannot tell what I/O redirections and fixups it should do; the calling program knows.

If the calling program is running with elevated privileges (SUID or SGID privileges), it is normal to want to turn those 'off' before running another program. Relying on the other program to know what to do is ... foolish.

烟凡古楼 2024-12-16 22:06:22

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

最后,forkexec 函数是 ~n 行应用程序代码(对于 n 的某个小值)。

我确实希望 Windows 有这样一个有用的 ForkProcess :(

快乐编码


。cnicutar 提到,写入时复制 (COW) 是使用的一种策略。

UNIX-like operating systems (at least newer Linux and BSD kernels) generally have a very efficient fork implementation -- it is "so cheap" that there are "threaded" implementations based upon it in some languages.

In the end the forkexec function is ~n -- for some small value of n -- lines of application code.

I sure wish windows had such a useful ForkProcess :(

Happy coding.


A cnicutar mentioned, Copy-On-Write (COW) is one strategy used.

青衫负雪 2024-12-16 22:06:22

有一个函数相当于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);
} 

There is a function that is equivalent to 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);
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文