fork() 与 CreateProcess()。系统调用与 API?
fork() vs. CreateProcess(). System call vs. API?
假设 APIs 通常与它们调用的系统调用相似(在某些情况下相同)....
我们在用户应用程序中调用的 fork() 是调用实际系统调用的 'API in POSIX' 'fork()'?还是直接调用fork()系统调用?
它与 Win32 API 中的 CreateProcess() 相比如何?
是CreateProcess()一个调用另一个系统调用的系统调用NTCreateProcess()系统调用或 CreateProcess() 是 Win32 API 中调用 NTCreateProcess() 系统调用的函数吗?
正如 Jeffy Coffin 所指出的,API 代表应用程序接口,是描述一组函数、相关类型和其他语言接口和特性的文档,供应用程序使用。 API 几乎可以是任何东西。例如 Stack Exchange 有一个 web API 可以被任何能够通过 Internet 发出 HTTP 请求的东西使用。
此外,正如 Jerry Coffin 所说,术语 "system call" 的定义不是很明确。就是一个API函数,实现了一个运营服务。您可能会争辩说 CreateProcess 和 NTCreateProcess 都不是系统调用。两者都是真正系统调用的 C 包装器,它是用汇编语言编写的位代码。另一方面,我认为它们都是系统调用。它们都提供对操作系统设施的访问,用于创建新进程而没有明显的额外附加功能。不管怎样,这并不重要。
我只能说 Linux 和 UNIX 变体,但我想 Windows 是相似的。
Does the fork() we invoke in our user application, a 'API in POSIX'
which invokes the actual system call 'fork()'? Or do we directly
invoke fork() system call?
在 Linux 中,fork(2)
是系统调用,但最近的 Linux 版本在大多数情况下不使用它。当您从 C 用户程序调用 fork(2)
时,您调用的是 glibc 包装器,而不是真正的系统调用 - 从最新版本开始,glibc 包装器调用 clone(2)
并将必要的标志传递给它以指示新进程的属性。 clone(2)
是真正的系统调用(参见 man 2 clone
)。
但是,即使您直接在 C 程序中调用 clone(2)
,您也会调用 glibc 包装函数。大多数原始系统调用在 glibc 中都有一个等效的包装函数,因为原始系统调用依赖于体系结构。
一些联机帮助页包括包装器和原始系统调用的原型。例如,clone(2)
的联机帮助页显示了两种变体:
SYNOPSIS
/* Prototype for the glibc wrapper function */
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
/* Prototype for the raw system call */
long clone(unsigned long flags, void *child_stack,
void *ptid, void *ctid,
struct pt_regs *regs);
您通常可以从联机帮助页中学到很多东西。 man 2 fork
在注释部分提到我上面说的:
NOTES
Under Linux, fork() is implemented using copy-on-write
pages, so the only penalty that it incurs is the time and memory
required to duplicate the parent's page tables, and to create a unique
task structure for the child.
Since version 2.3.3, rather than invoking the kernel's fork() system
call, the glibc fork() wrapper that is provided as part of the NPTL
threading implementation invokes clone(2) with flags that provide the
same effect as the traditional system call. (A call to fork() is
equivalent to a call to clone(2) specifying flags as just SIGCHLD.) The glibc wrapper invokes any fork handlers that
have been established using pthread_atfork(3).
(如果您想知道,NPTL 代表 Native POSIX Threads Library)
TL;DR 在编程时,您永远不会真正直接调用系统调用。您调用 glibc 包装器来处理原始系统调用调用的细节。
假设 APIs 通常与它们调用的系统调用相似(在某些情况下相同)....
我们在用户应用程序中调用的 fork() 是调用实际系统调用的 'API in POSIX' 'fork()'?还是直接调用fork()系统调用?
它与 Win32 API 中的 CreateProcess() 相比如何?
是CreateProcess()一个调用另一个系统调用的系统调用NTCreateProcess()系统调用或 CreateProcess() 是 Win32 API 中调用 NTCreateProcess() 系统调用的函数吗?
正如 Jeffy Coffin 所指出的,API 代表应用程序接口,是描述一组函数、相关类型和其他语言接口和特性的文档,供应用程序使用。 API 几乎可以是任何东西。例如 Stack Exchange 有一个 web API 可以被任何能够通过 Internet 发出 HTTP 请求的东西使用。
此外,正如 Jerry Coffin 所说,术语 "system call" 的定义不是很明确。就是一个API函数,实现了一个运营服务。您可能会争辩说 CreateProcess 和 NTCreateProcess 都不是系统调用。两者都是真正系统调用的 C 包装器,它是用汇编语言编写的位代码。另一方面,我认为它们都是系统调用。它们都提供对操作系统设施的访问,用于创建新进程而没有明显的额外附加功能。不管怎样,这并不重要。
我只能说 Linux 和 UNIX 变体,但我想 Windows 是相似的。
Does the fork() we invoke in our user application, a 'API in POSIX' which invokes the actual system call 'fork()'? Or do we directly invoke fork() system call?
在 Linux 中,fork(2)
是系统调用,但最近的 Linux 版本在大多数情况下不使用它。当您从 C 用户程序调用 fork(2)
时,您调用的是 glibc 包装器,而不是真正的系统调用 - 从最新版本开始,glibc 包装器调用 clone(2)
并将必要的标志传递给它以指示新进程的属性。 clone(2)
是真正的系统调用(参见 man 2 clone
)。
但是,即使您直接在 C 程序中调用 clone(2)
,您也会调用 glibc 包装函数。大多数原始系统调用在 glibc 中都有一个等效的包装函数,因为原始系统调用依赖于体系结构。
一些联机帮助页包括包装器和原始系统调用的原型。例如,clone(2)
的联机帮助页显示了两种变体:
SYNOPSIS
/* Prototype for the glibc wrapper function */
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
/* Prototype for the raw system call */
long clone(unsigned long flags, void *child_stack,
void *ptid, void *ctid,
struct pt_regs *regs);
您通常可以从联机帮助页中学到很多东西。 man 2 fork
在注释部分提到我上面说的:
NOTES
Under Linux, fork() is implemented using copy-on-write pages, so the only penalty that it incurs is the time and memory required to duplicate the parent's page tables, and to create a unique task structure for the child.
Since version 2.3.3, rather than invoking the kernel's fork() system call, the glibc fork() wrapper that is provided as part of the NPTL threading implementation invokes clone(2) with flags that provide the same effect as the traditional system call. (A call to fork() is equivalent to a call to clone(2) specifying flags as just SIGCHLD.) The glibc wrapper invokes any fork handlers that have been established using pthread_atfork(3).
(如果您想知道,NPTL 代表 Native POSIX Threads Library)
TL;DR 在编程时,您永远不会真正直接调用系统调用。您调用 glibc 包装器来处理原始系统调用调用的细节。