C语言 系统调用 vs 函数调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2668747/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
System call vs Function call
提问by Ankur
What is the difference between a system call and a function call? Is fopen() a system call or a function call?
系统调用和函数调用有什么区别?fopen() 是系统调用还是函数调用?
回答by Thomas
A system call is a call into kernel code, typically performed by executing an interrupt. The interrupt causes the kernel to take over and perform the requested action, then hands control back to the application. This mode switching is the reason that system calls are slower to execute than an equivalent application-level function.
系统调用是对内核代码的调用,通常通过执行中断来执行。中断导致内核接管并执行请求的操作,然后将控制权交还给应用程序。这种模式切换是系统调用比等效的应用程序级函数执行速度慢的原因。
fopenis a function from the C library that, internally, performs one or more system calls. Generally, as a C programmer, you rarely need to use system calls because the C library wraps them for you.
fopen是来自 C 库的一个函数,它在内部执行一个或多个系统调用。通常,作为 C 程序员,您很少需要使用系统调用,因为 C 库为您包装了它们。
回答by Tom
fopen is a function call.
fopen 是一个函数调用。
A system call interacts with the underlying OS, which manages resources. Its orders of magnitud more expensive than a function call, because many steps have to be taken to preserve the state of the process that made the syscall.
系统调用与管理资源的底层操作系统交互。它的数量级比函数调用更昂贵,因为必须采取许多步骤来保存进行系统调用的进程的状态。
On *nix systems, fopen wraps open, which makes the system call (open is the C - wrapper for the syscall). The same happens with fread /read, fwrite / write , etc..
在 *nix 系统上, fopen 包装 open,它进行系统调用(open 是系统调用的 C 包装器)。fread /read、fwrite / write 等也会发生同样的情况。
Herethere's a nice description of the tasks executed by a unix syscall.
这里有一个由 unix 系统调用执行的任务的很好的描述。
回答by Houcheng
Actually, the system call is not related to function call. The only common of these two mechanism is that they both provides services to the caller.
实际上,系统调用与函数调用无关。这两种机制的唯一共同点是它们都为调用者提供服务。
From view of thread execution to see system call:
A system call is function for application mode program to request services provided by underline OS. The system call will bring the running thread from user mode into kernel mode, execute the system call handler function, then return back to user mode.
Syscall Parameters:
The parameter of a system call is (syscall number, params...). The meaning and format of params depends on syscall number.
From view of syscall library provided to userland program:
The user mode program usually calls glibc's library to call system call. For example, the open() function in glibc:
- put system call number SYS_OPEN in eax register
- request system call by calling a software interrupt or sys_enter instruction
从线程执行来看系统调用:
系统调用是应用程序模式程序请求下划线操作系统提供的服务的功能。系统调用会将正在运行的线程从用户态带入内核态,执行系统调用处理函数,然后返回到用户态。
系统调用参数:
系统调用的参数是 (syscall number, params...)。params 的含义和格式取决于系统调用号。
从提供给用户态程序的系统调用库来看:
用户态程序通常调用glibc 的库来调用系统调用。例如,glibc 中的 open() 函数:
- 将系统调用号 SYS_OPEN 放入 eax 寄存器
- 通过调用软件中断或 sys_enter 指令来请求系统调用
回答by SK-logic
If you're using Linux you can monitor system calls performed by an application:
如果您使用的是 Linux,您可以监控应用程序执行的系统调用:
strace appname ...
strace 应用程序名称 ...
Its output might give you a good insight on what's going on within libc, and which functions are actually system calls.
它的输出可能会让您很好地了解 libc 中发生的事情,以及哪些函数实际上是系统调用。
回答by DVK
System callactually calls out to an API executed by the kernel space. With all the associated costs this assumes (see Wiki, or this link for details)
系统调用实际上调用由内核空间执行的 API。假设所有相关成本(请参阅 Wiki 或此链接以获取详细信息)
A function call is a call to a piece of code in user space.
函数调用是对用户空间中的一段代码的调用。
However, please note that a function call MIGHT be to a function which in the process of its execution does system calls - "fopen" being one of such examples. So while the call to fopen itself is a call to a function, doesn't mean that the system call will not happen to handle the actual IO.
但是,请注意,函数调用可能是针对在执行过程中进行系统调用的函数——“fopen”就是这样的例子之一。因此,虽然对 fopen 本身的调用是对函数的调用,但这并不意味着系统调用不会碰巧处理实际的 IO。
回答by Hassan Syed
A point of view to add to this discussion is that a function call generally in the most optimistic case has overhead of a a few 8-bit instructions (4-10 on average)in x86.
要添加到此讨论中的一个观点是,在最乐观的情况下,函数调用通常在 x86 中具有少量 8 位指令(平均 4-10 条)的开销。
A system call has the following properties.
系统调用具有以下属性。
- It Executes far more instructions, it has to freeze a process instead of simply the stack state.
- The timing involved is mostly non-deterministic.
- It is often a scheduling spot, and the scheduler may choose to reschedule.
- 它执行更多的指令,它必须冻结进程而不是简单的堆栈状态。
- 所涉及的时间大多是不确定的。
- 它通常是一个调度点,调度器可以选择重新调度。
For these three primitive reasons (there are probably more), one should reduce the amount of system calls where possible -- e.g., networked system software keeps socket handles (and other application specific internal data structures used by a connection) around to assign to new connection, why bother the kernel ?
由于这三个原始原因(可能还有更多),应该尽可能减少系统调用的数量——例如,网络系统软件保留套接字句柄(以及连接使用的其他应用程序特定内部数据结构)以分配给新的连接,为什么要打扰内核?
Remember that software is built like a upside down pyramid. System calls are at the base.
请记住,软件的构建就像一个倒金字塔。系统调用是基础。
回答by u6949852
The question has excellent answers already, but I think I can add something (one segment from ostepthat isn't already in other answers
这个问题已经有了很好的答案,但我想我可以添加一些东西(来自ostep 的一个片段,它已经不在其他答案中了
Sometimes system call and function call have the same signature, for example, open():
有时系统调用和函数调用具有相同的签名,例如open():
open()-system call
open()-系统调用
--- ~/Documents ? man open(2)
OPEN(2) Linux Programmer's Manual OPEN(2)
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
...
open()-function call
open()- 函数调用
$ man open(3)
--- ~/Documents ?
OPEN(3P) POSIX Programmer's Manual OPEN(3P)
...
int open(const char *path, int oflag, ...);
...
Quoting form OSTEP
报价单OSTEP
You may wonder why a call to a system call, such as
open()orread(), looks exactly like a typical procedure callin C; that is, if it looks just like a procedure call, how does the system know it's a system call, and do all the right stuff? The simple reason: it is a procedure call, but hidden inside that procedure callis the famous trap instruction. More specifically, when you callopen()(for example), you are executing a procedure callinto the C library. Therein, whether foropen()or any of the other system callsprovided, the library uses an agreed-upon calling convention with the kernel to put the arguments to open in well-known locations(e.g., on the stack, or in specific registers), puts the system-callnumber into a well-known location as well (again, onto the stackor a register), and then executes the aforementioned trap instruction. The code in the library after the trapunpacks return values and returns control to the program that issued the system call. Thus, the parts of the C library that make system callsare hand-coded in assembly, as they need to carefully follow convention in order to process arguments and return values correctly, as well as execute the hardware-specific trap instruction. And now you know why you personally don't have to write assembly code to trapinto an OS; somebody has already written that assembly for you.
您可能想知道为什么对系统调用(例如
open()or )的调用read()看起来与C 中的典型过程调用完全一样;也就是说,如果它看起来就像一个过程调用,系统如何知道它是一个系统调用,并执行所有正确的操作?原因很简单:它是一个过程调用,但隐藏在该过程调用中的是著名的陷阱指令。更具体地说,当您调用open()(例如)时,您正在执行对 C 库的过程调用。其中,无论是 foropen()还是任何其他系统调用提供,库使用与内核商定的调用约定将要打开的参数放在众所周知的位置(例如,在堆栈上,或在特定寄存器中),将系统调用号放入众所周知的位置同样(再次,到堆栈或寄存器上),然后执行上述陷阱指令。陷阱之后库中的代码解包返回值并将控制权返回给发出系统调用的程序。因此,进行系统调用的 C 库部分在汇编中手工编码,因为它们需要仔细遵循约定以正确处理参数和返回值,以及执行特定于硬件的陷阱指令。现在您知道为什么您个人不必编写汇编代码来陷入操作系统;有人已经为您编写了该程序集。
回答by Eli Bendersky
Just to complete the picture presented by the others, fopenis commonly implementedas a wrapper around open, which is also a user-accessible function. fopenis, in a sense, higher-level than opensince the FILE*structure it returns encapsulates stuff for the user. Some users use opendirectly for special needs. Therefore it wouldn't be right to call fopena "system call" in any way. Nor does it execute system calls directly, since openis also a function callable by the user.
只是为了完成其他人展示的图片,通常fopen是作为一个包装器来实现的,这也是一个用户可以访问的功能。从某种意义上说,比因为它返回的结构为用户封装了东西而更高。有的用户为了特殊需要直接使用。因此,以任何方式调用“系统调用”都是不对的。它也不直接执行系统调用,因为它也是一个可由用户调用的函数。openfopenopenFILE*openfopenopen
回答by Mark Wilkins
fopenis a function call, but it may sometimes be referred to as a system call because it is ultimately handled by the "system" (the OS). fopenis built into the C runtime library.
fopen是函数调用,但有时也称为系统调用,因为它最终由“系统”(操作系统)处理。 fopen内置于C 运行时库中。
回答by dhokar.w
System call is executed at kernet level and not in user spce because it requires some prievilege to access the hardware.
系统调用在内核级别而不是在用户 spce 中执行,因为它需要一些特权才能访问硬件。
Therfore when programming in user space and making some ordinary function call like fopenin C language the libc generally wrap this function to specific code code where an interrupt is generated to switch from user space to kernel space , then in kernel space the required system call to perform the functionality of the function call at hardware level will be executed in kernel space .
因此,当在用户空间编程并像fopen在 C 语言中那样进行一些普通的函数调用时,libc 通常将此函数包装到特定的代码代码中,其中产生中断以从用户空间切换到内核空间,然后在内核空间中执行所需的系统调用。硬件级别的函数调用功能将在内核空间中执行。

