为什么 malloc() 被视为库调用而不是系统调用?
为什么 malloc() 被视为标准 C 库函数而不是系统调用?操作系统似乎负责处理所有内存分配请求。
Why is malloc() considered a standard C library function and not a system call? It seems like the OS is responsible for handling all memory allocation requests.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当然可能将
malloc
和free
实现为系统调用,但很少这样做。系统调用是对操作系统内核的调用。例如,在 POSIX 系统(Linux、UNIX...)上,
read
和write
是系统调用。当 C 程序调用 read 时,它可能会调用一个包装器,该包装器会执行向内核发出请求所需的任何操作,然后将结果返回给调用者。事实证明,进行内存管理最有效的方法是使用较低级别的系统调用(参见
brk
和sbrk
)来扩展当前进程的数据段,然后使用库调用(malloc
、free
等)来管理该段内的内存。该管理不需要与内核进行任何交互;这只是在当前进程中执行的指针操作。如果malloc
函数需要比当前可用的内存更多的内存,则会调用系统调用,例如brk
或sbrk
,但是许多malloc
调用根本不需要与内核进行任何交互。上面的内容是针对 Linux/POSIX/UNIX 系统的。例如,Windows 的细节会有所不同,但总体设计可能相似。
请注意,某些 C 标准库函数通常直接作为系统调用实现。
time
就是一个例子(但正如 Nick ODell 在评论中指出的那样,time
调用通常可以在不与内核交互的情况下执行)。It would certainly be possible to implement
malloc
andfree
as system calls, but it's rarely if ever done that way.System calls are calls into the OS kernel. For example, on POSIX systems (Linux, UNIX, ...),
read
andwrite
are system calls. When a C program callsread
, it's probably calling a wrapper that does whatever is needed to make a request to the kernel and then return the result to the caller.It turns out that the most efficient way to do memory management is to use lower-level system calls (see
brk
andsbrk
) to expand the current process's data segment, and then use library calls (malloc
,free
, etc.) to manage memory within that segment. That management doesn't require any interaction with the kernel; it's all just pointer manipulation performed within the current process. Themalloc
function will invoke a system call such asbrk
orsbrk
if it needs more memory than is currently available, but manymalloc
calls won't require any interaction with the kernel at all.The above is fairly specific to Linux/POSIX/UNIX systems. The details will be a bit different for Windows for example, but the overall design is likely to be similar.
Note that some C standard library functions are typically implemented directly as system calls.
time
is one example (but as Nick ODell points out in a comment, atime
call can often be performed without interacting with the kernel).好吧,既是又不是。
实际上,它更多地取决于您的特定系统,而不是 C。
大多数操作系统都会在一定大小的主干中分配内存。通常称为页面。页面大小可能不同。在特定系统上可能有多种受支持的页面大小。 4K 是许多系统上的典型页面大小,但可能支持更大的大页面。
但是,是的......最终只有一个实体可以分配内存。操作系统。除非你使用的是裸机,其他代码可以处理它 - 如果甚至支持的话。
简短的答案是:因为
malloc
不是操作系统/系统调用。时期。详细说明一下。一次
malloc
调用可能会导致系统调用,但下一次malloc
可能不会。例如:您使用
malloc
请求 100 个字节。malloc
可能决定调用操作系统。操作系统为您提供 4K。在下一个malloc
中,您请求 500 字节。然后“中间层”可以只提供来自先前系统调用已经提供的主干的 500 字节。所以不...通过
malloc
进行内存分配可能不会导致任何系统调用来分配更多内存。这完全取决于您的特定系统。而 C 标准并不关心。
但
malloc
不是系统调用。malloc
在需要时使用其他系统调用。Well, both yes and no
It actually depends more on your specific system than it depend on C.
Most OS allocates memory in trunks of some size. Typically called a page. The page size may differ. And on a specific system there may be several supported page-sizes. 4K is a typical page-size on many systems but huge page much bigger may be supported.
But yes... at the end of the day there is only one entity that can allocate memory. The OS. Unless you are on bare-metal where other code can handle it - if even supported.
The short answer is: Because
malloc
isn't a OS/systemcall. Period.To elaborate a bit more. One
malloc
call may lead to a systemcall but the nextmalloc
may not.For instance: You request 100 bytes using
malloc
.malloc
may decide to call the OS. The OS gives you 4K. In your nextmalloc
you request 500 byte. Then the "layer in between" can just give the 500 bytes from the trunk already provided by the previous syscall.So no... memory allocation via
malloc
may not lead to any syscall for alocation of more memory.It's all very dependent on your specific system. And the C standard doesn't care.
But
malloc
is not a syscall.malloc
uses other syscalls when needed.出于性能原因,每次程序需要内存时都向操作系统请求内存并不是一个好主意。造成这种情况的原因有几个:
操作系统以称为页的单位管理内存。页的长度通常为 4096 字节。 (但某些架构或操作系统使用更大的页面。)操作系统无法为进程分配内存在比页面还小的块中。
假设您需要 10 个字节来存储一个字符串。分配 4096 字节并且只使用前 10 个字节是非常浪费的。内存分配器可以向操作系统请求一个页面,并将该页面分割成更小的分配。
系统调用需要上下文切换。相对于在同一程序中调用函数,上下文切换的成本很高(在 x86 系统上约为 100 ns)。同样,最好请求更大的内存块,并将其重新用于多次分配。
对于某些库调用,例如
read()
,库中的实现非常简单:它调用同名的系统调用。对库函数read()
的一次调用会产生对read()
的一次系统调用。将 read() 描述为系统调用是合理的,因为所有工作都是在内核中完成的。malloc()
的情况更为复杂。没有名为malloc()
的系统调用,库调用malloc()
实际上会使用系统调用sbrk()
、brk()
或mmap()
,具体取决于您的分配大小和您使用的实现。大多数时候,它根本不进行系统调用!如何实现
malloc()
有许多不同的选择。因此,您会看到许多不同的竞争实现,例如 jemalloc 或 tcmalloc。For performance reasons, it's not a good idea to ask the OS for memory every time the program needs memory. There are a few reasons for this:
The OS manages memory in units called pages. Pages are typically 4096 bytes long. (But some architectures or operating systems use larger pages.) The OS can't allocate memory to a process in a chunk smaller than a page.
Imagine you need 10 bytes to store a string. It would be very wasteful to allocate 4096 bytes and only use the first 10. A memory allocator can ask the OS for a page, and slice that page into smaller allocations.
A system call requires a context switch. A context switch is expensive, (~100 ns on x86 systems) relative to calling a function in the same program. Again, it is better to ask for a larger chunk of memory, and re-use it for many allocations.
For some library calls, like
read()
the implementation in the library is very simple: it calls the system call of the same name. One call to the library functionread()
produces one system call toread()
. It's reasonable to describeread()
as a system call, because all the work is being done in the kernel.The story with
malloc()
is more complicated. There's no system call calledmalloc()
, and the library callmalloc()
will actually use the system callssbrk()
,brk()
, ormmap()
, depending on the size of your allocation and the implementation you're using. Much of the time, it makes no system call at all!There are many different choices in how to implement
malloc()
. For that reason, you'll see many different competing implementations, such as jemalloc, or tcmalloc.因为它是 C 标准库的一部分。
它不是。操作系统通常会为给定进程分配一些内存空间,但之后如何使用内存则取决于进程。使用标准库进行内存分配等操作可以将您的代码与任何给定操作系统的详细信息隔离开来,从而使您的代码更加可移植。给定的
malloc
实现最终可能会进行系统调用来获取内存,但是否执行或不执行或有时执行是一个实现细节。Because it's part of the C standard library.
It's not. An operating system typically allocates some memory space for a given process, but how the memory is used after that is up to the process. Using the standard library for things like memory allocation insulates your code from the details of any given operating system, which makes your code a lot more portable. A given implementation of
malloc
might ultimately make a system call to obtain memory, but whether it does or doesn't or does some of the time is an implementation detail.