为什么malloc()被认为是标准的C库函数,而不是系统调用?看起来操作系统负责处理所有内存分配请求。
malloc
和free
作为系统调用是完全可行的,但这种方式很少被使用。read
和write
就是系统调用。当C程序调用read
时,它可能调用一个包装器,该包装器执行所有必要的操作以向内核发出请求,然后将结果返回给调用者。brk
和sbrk
)来扩展当前进程的数据段,然后使用库调用(如malloc
、free
等)在该段内管理内存。该管理不需要与内核的任何交互;这只是在当前进程内执行的指针操作。如果malloc
函数需要比当前可用的内存更多的内存,则会调用像brk
或sbrk
这样的系统调用,但许多malloc
调用根本不需要与内核进行任何交互。time
就是一个例子(但正如Nick ODell在评论中指出的那样,time
调用经常可以在不与内核交互的情况下执行)。time
函数并不是一个很好的例子,因为如果启用了vDSO,它可以在没有系统调用的情况下获得:https://unix.stackexchange.com/questions/316074/why-dont-linux-utils-use-a-system-call-to-get-the-current-time 但总的来说,你的帖子是正确的。非常棒! - Nick ODellread()
,在库中的实现非常简单:它会调用同名的系统调用。一次对库函数read()
的调用会产生一次对read()
的系统调用。可以合理地将read()
描述为系统调用,因为所有工作都是在内核中完成的。
malloc()
的情况就更加复杂了。没有一个叫做malloc()
的系统调用,而库调用malloc()
实际上会使用sbrk()
、brk()
或mmap()
等系统调用,具体取决于你的分配大小和你使用的实现方式。很多时候,它根本不会进行系统调用!malloc()
。因此,你会看到许多竞争的实现,比如jemalloc或tcmalloc。malloc
实现中使用的brk/sbrk
调用确实是系统调用。 - Eugene Sh.brk/sbrk
正在改变初始分配。 - Eugene Sh.malloc
的实现方式并不重要。标准库的一个重要特性是它隔离了程序员与操作系统特定的细节。你提到brk
和sbrk
这一事实表明你有一个非常Unix中心的观点,这并没有错,但是还有很多其他没有这些调用的系统存在。即使我在Arduino上工作,malloc()
仍然可以工作,尽管根本没有真正的操作系统。 - Caleb
malloc
是一个库函数,可以有各种实现方式,包括一些可能使用系统调用的方式(也可能不使用)。 - Eugene Sh.syscall()
本身也是作为一个库函数(尽管是用汇编语言实现的)。除非您编写自己的汇编程序直接调用CPU的实际系统调用指令,否则您正在调用一个库函数。 - Andrew Henle