系统调用与函数调用

发布于 2024-08-29 13:50:23 字数 43 浏览 8 评论 0原文

系统调用和函数调用有什么区别? fopen() 是系统调用还是函数调用?

What is the difference between a system call and a function call? Is fopen() a system call or a function call?

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

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

发布评论

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

评论(10

旧城烟雨 2024-09-05 13:50:23

系统调用是对内核代码的调用,通常通过执行中断来执行。中断导致内核接管并执行请求的操作,然后将控制权交还给应用程序。这种模式切换是系统调用执行速度比等效应用程序级函数慢的原因。

fopen 是 C 库中的一个函数,它在内部执行一个或多个系统调用。一般来说,作为 C 程序员,您很少需要使用系统调用,因为 C 库为您包装了它们。

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.

fopen is 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.

爱人如己 2024-09-05 13:50:23

fopen 是一个函数调用。

系统调用与管理资源的底层操作系统交互。它的数量级比函数调用昂贵,因为必须采取许多步骤来保存进行系统调用的进程的状态。

在 *nix 系统上,fopen 包装 open,从而进行系统调用(open 是系统调用的 C 包装器)。 fread /read、fwrite / write 等也会发生同样的情况。

此处有一个关于 unix 系统调用执行的任务的很好的描述。

fopen is a function call.

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..

Here there's a nice description of the tasks executed by a unix syscall.

有深☉意 2024-09-05 13:50:23

实际上,系统调用与函数调用无关。这两种机制唯一的共同点是它们都向调用者提供服务。

  • 从线程执行的角度看系统调用:

    系统调用是应用程序模式程序请求下层操作系统提供的服务的函数。系统调用会将正在运行的线程从用户模式带入内核模式,执行系统调用处理函数,然后返回用户模式。

  • 系统调用参数:

    系统调用的参数是(系统调用号,参数...)。 params 的含义和格式取决于系统调用号。

  • 从提供给用户层程序的系统调用库来看:

    用户态程序通常会调用glibc的库来调用系统调用。例如glibc中的open()函数:

    1. 将系统调用号SYS_OPEN放入eax寄存器
    2. 通过调用软件中断或sys_enter指令请求系统调用

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:

    1. put system call number SYS_OPEN in eax register
    2. request system call by calling a software interrupt or sys_enter instruction
百合的盛世恋 2024-09-05 13:50:23

系统调用实际上是调用内核空间执行的API。考虑到所有相关成本(请参阅 Wiki 或此链接了解详细信息),

函数调用是对用户空间中的一段代码的调用。

但是,请注意,函数调用可能是在执行过程中执行系统调用的函数 - “fopen”就是此类示例之一。因此,虽然对 fopen 本身的调用是对函数的调用,但这并不意味着系统调用不会处理实际的 IO。

System call actually calls out to an API executed by the kernel space. With all the associated costs this assumes (see Wiki, or this link for details)

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.

她说她爱他 2024-09-05 13:50:23

在此讨论中需要补充的一个观点是,在 x86 中,在最乐观的情况下,函数调用通常会产生一些 8 位指令(平均 4-10 个)的开销。

系统调用具有以下属性。

  1. 它执行更多的指令,它必须冻结进程而不是简单地冻结堆栈状态。
  2. 所涉及的时间大多是不确定的。
  3. 往往是一个调度点,调度者可能会选择重新调度。

由于这三个原始原因(可能还有更多),我们应该尽可能减少系统调用的数量——例如,网络系统软件保留套接字句柄(以及连接使用的其他应用程序特定的内部数据结构)以分配给新的连接,为什么要打扰内核?

请记住,软件的构建就像一个倒置的金字塔。系统调用位于底层。

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.

A system call has the following properties.

  1. It Executes far more instructions, it has to freeze a process instead of simply the stack state.
  2. The timing involved is mostly non-deterministic.
  3. 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.

欢你一世 2024-09-05 13:50:23

这个问题已经有了很好的答案,但我想我可以添加一些东西(来自 ostep其他答案中尚未包含

有时系统调用和函数调用具有相同的签名,例如,open()

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()-函数调用

$ man open(3)

--- ~/Documents » 
OPEN(3P)                        POSIX Programmer's Manual          OPEN(3P)
...

int open(const char *path, int oflag, ...);

...

引用形式OSTEP

您可能想知道为什么对系统调用的调用(例如open()read())看起来与典型的C中的过程调用;也就是说,如果它看起来就像一个过程调用,系统如何知道它是一个系统调用,并执行所有正确的操作?原因很简单:它是一个过程调用,但在过程调用内部隐藏着著名的陷阱指令。更具体地说,当您调用 open()(例如)时,您正在对 C 库执行过程调用。其中,无论是对于 open() 还是任何其他提供的系统调用,库都使用与内核商定的调用约定来将参数放入 open 中-已知位置(例如,在堆栈上,或在特定的寄存器中),将系统调用编号放入众所周知的位置,如下所示好(再次,进入堆栈寄存器),然后执行前面提到的陷阱指令。库中的代码在陷阱之后解压返回值并将控制权返回给发出系统调用的程序。因此,C 库中进行系统调用的部分是在汇编中手动编码的,因为它们需要仔细遵循约定才能正确处理参数和返回值,以及执行硬件 -具体的陷阱指令。现在您知道为什么您个人不需要编写汇编代码来捕获到操作系统中了;有人已经为您编写了该程序集。

The question has excellent answers already, but I think I can add something (one segment from ostepthat isn't already in other answers

Sometimes system call and function call have the same signature, for example, open():

open()-system call

--- ~/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

$ man open(3)

--- ~/Documents » 
OPEN(3P)                        POSIX Programmer's Manual          OPEN(3P)
...

int open(const char *path, int oflag, ...);

...

Quoting form OSTEP

You may wonder why a call to a system call, such as open() or read(), looks exactly like a typical procedure call in 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 call is the famous trap instruction. More specifically, when you call open() (for example), you are executing a procedure call into the C library. Therein, whether for open() or any of the other system calls provided, 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-call number into a well-known location as well (again, onto the stack or a register), and then executes the aforementioned trap instruction. The code in the library after the trap unpacks return values and returns control to the program that issued the system call. Thus, the parts of the C library that make system calls are 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 trap into an OS; somebody has already written that assembly for you.

有木有妳兜一样 2024-09-05 13:50:23

如果您使用的是 Linux,您可以通过 监视应用程序执行的系统调用strace

strace /path/to/app

它的输出可能会让您深入了解 libc 中发生的情况,以及哪些函数实际上是系统调用。

If you're using Linux you can monitor system calls performed by an application via strace:

strace /path/to/app

Its output might give you a good insight on what's going on within libc, and which functions are actually system calls.

预谋 2024-09-05 13:50:23

fopen 是一个函数调用,但有时也称为系统调用,因为它最终由“系统”(操作系统)处理。 fopen 内置于 C 运行时库中。

fopen is a function call, but it may sometimes be referred to as a system call because it is ultimately handled by the "system" (the OS). fopen is built into the C runtime library.

时光沙漏 2024-09-05 13:50:23

为了完成其他人提供的图片,fopen通常实现作为open的包装器,这也是一个用户可访问的函数。从某种意义上说,fopenopen 更高级别,因为它返回的 FILE* 结构为用户封装了内容。有些用户出于特殊需要直接使用open。因此,以任何方式将 fopen 称为“系统调用”都是不正确的。它也不会直接执行系统调用,因为open也是一个可由用户调用的函数。

Just to complete the picture presented by the others, fopen is commonly implemented as a wrapper around open, which is also a user-accessible function. fopen is, in a sense, higher-level than open since the FILE* structure it returns encapsulates stuff for the user. Some users use open directly for special needs. Therefore it wouldn't be right to call fopen a "system call" in any way. Nor does it execute system calls directly, since open is also a function callable by the user.

棒棒糖 2024-09-05 13:50:23

系统调用在内核级别执行,而不是在用户空间中执行,因为它需要某些权限才能访问硬件。

因此,当在用户空间编程并进行一些普通函数调用(例如C语言中的fopen)时,libc通常将此函数包装到特定的代码中,在代码中产生中断以从用户空间切换到内核空间,然后在内核空间 执行硬件级别的函数调用功能所需的系统调用将在内核空间中执行。

System call is executed at kernet level and not in user spce because it requires some prievilege to access the hardware.

Therfore when programming in user space and making some ordinary function call like fopen in 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 .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文