C标准库和系统调用

4
有没有一种方法可以找出哪些C标准库函数会进行系统调用?像openclosemalloc这些函数很明显,但是是否有某种列表可以查看?例如,strcpy是否会进行系统调用,或者time.h中的任何函数是否会进行系统调用?

2
这很可能取决于具体的实现。您有特定的系统感兴趣吗? - templatetypedef
哎呀...这正是我担心的。:( - theshadow322
malloc() 不总是会进行系统调用。 - tristan
2个回答

7
我会假设您的问题是关于性能方面的,因为在许多情况下,运行时间完全被系统调用所占据。
现在,虽然这取决于具体实现(甚至"系统调用"是否存在也取决于具体实现),但进行推理和做出合理猜测的一个好方法是将"系统调用"视为"user-to-kernel-to-user"特权转换,因为这就是系统调用的全部内容。
以strcpy为例,它将一个字符串从一个数组(位于进程的内存空间)复制到另一个数组(同样位于进程的内存空间)。它所做的事情除了处理这些字符串之外都不涉及任何数据,因此在这个操作中进入内核空间是非常罕见的。
另一方面,考虑来自time.h的time函数。它返回当前系统时间。这是一个共享的系统资源,因此您可能希望它需要进入内核空间以读取内核记录的当前时间。传统上,您是正确的。但是,现代Linux版本在某些arch上将一页内核内存映射到每个用户进程中作为只读 - 包含某些信息的页面,只有内核才能更新,例如系统时间,但所有进程都可以从用户空间自由读取,而不会泄露任何秘密数据。因此这个问题更加模糊。
最后,您还有像open或unlink这样的操作必须涉及用户到内核到用户的转换,因为它们处理共享资源(文件系统),必须执行权限强制。
如果您想要更加实证的方法来回答您的问题,可以编写一个简短的程序来调用您感兴趣的每个函数,并在strace下运行它。

即使是“open”操作也不一定涉及内核转换。 在早期的Windows版本中,如果您打开一个控制台文件句柄(例如“CONIN $”),则用户模式存根将返回一个常量句柄(表示“当前控制台的输入流”)。 我不知道现在是否仍然如此。 - arx
我假设使用符合POSIX标准的open版本。返回与已经打开的文件描述符匹配的文件描述符远远不符合标准... - R.. GitHub STOP HELPING ICE

1
当您的程序需要与内核通信时,会发出系统调用。如果strcpy进行系统调用,则效率非常低,因为这需要中断;您的代码停止运行,发生上下文切换,CPU的执行模式更改(以具有更多特权),中断处理程序将运行,然后您的代码将继续运行。这是假设操作系统不决定在中断之后运行另一个进程或完全停止您的代码(例如在等待读取时)。
您可以通过问自己这个问题来回答问题:我能写这个函数吗?(能否物理上实现?)您可以编写自己的strcpy,但不能打开或读取。您可以编写自己的fopen,但它必须调用open。
维基百科上有一个很好的系统调用类别列表。它会让您了解何时需要系统调用。

这篇文章展示了如何在汇编中调用中断(这是唯一能够到达执行此操作的代码位置)。


+1 我喜欢“我可以写这个函数吗?”的教学方法。请注意它不完全适用的极端情况,比如我提到的 time 示例。 (如果你知道内核如何将必要的数据映射到用户空间内存,并知道其格式,那么你“可能”可以编写 time 函数,但它会很脆弱,因为内核的细节可能会发生变化。因此,如果想避免系统调用,则需要使用内核提供的代码。) - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接