系统调用开销

时间:2014-05-11 23:38:31

标签: process operating-system system-calls context-switch os161

我刚开始研究系统调用。              我想知道在进行系统调用时导致开销的原因。

例如, 如果我们考虑getpid(),当对getpid()进行系统调用时,我的猜测是如果控件当前在子进程中,则必须进行上下文切换以进入父进程以获取pid。这会导致开销吗?

当调用getpid()时,会在用户空间边界上进行一些元数据传输并进入和退出内核。那么用户空间和内核之间的不断切换是否会导致一些开销?

3 个答案:

答案 0 :(得分:6)

我在x86-64 Linux(用-O3编译)上做了一些更精确的基准测试:

ns    relative(rounded) function
4.89  1      regular_function  //just a value return
6.05  1      getpid   //glibc caches this one (forks invalidate the cached value)
17.7  4      sysconf(_SC_PAGESIZE)
22.6  5      getauxval(AT_EUID)
25.4  5      sysconf(_SC_NPROCESSORS_ONLN)
27.1  6      getauxval(AT_UID)
54.1  11     gettimeofday
235   48     geteuid
261   53     getuid
264   54     getppid
314   64     sysconf(_SC_OPEN_MAX)
622   127    pread@0 // IO funcs benchmarked with 1 bytes quantities
638   130    read    // through a 1 Gigabyte file
1690  346    write
1710  350    pwrite@0

最便宜的“系统调用”是通过辅助向量(~20-30ns)的那些。中间的调用(~250-310ns)应该最准确地反映平均开销,因为在内核中不应该有很多工作要做。

为了进行比较, malloc + free 对具有小尺寸请求(< 64字节=>无系统调用)的成本约为 70-80ns (请参阅我的回答at Cost of static memory allocation vs dynamic memory allocation in C)。

https://softwareengineering.stackexchange.com/questions/311165/why-isnt-there-generic-batching-syscall-in-linux-bsd/350173有一些关于如何最小化系统调用开销的有趣想法。

答案 1 :(得分:4)

请原谅(而不是限定每一句话)。

对系统服务的调用(例如返回进程信息)具有用户模式shell。此shell触发一个异常,该异常通过调用内核模式系统服务的系统调度表进行路由。

切换到内核模式需要类似于进程上下文切换的东西。例如,它需要从用户堆栈更改为kern堆栈(以及其他依赖于系统的更改)。

调用进程提供用户模式返回缓冲区。在出于安全目的编写响应数据之前,系统系统服务将检查以确保它是有效的用户模式缓冲区。

像getpid这样的库函数只返回有关当前进程的信息,可能不需要切换到内核模式。

答案 2 :(得分:3)

  

例如,如果我们考虑getpid(),当对getpid()进行系统调用时,我的猜测是如果控件当前在子进程中,则必须进行上下文切换以进入父进程得到pid。

此处不需要上下文切换到子进程 - 内核应该拥有自己可用的所有必要数据。在大多数情况下,内核只会将上下文切换到调度程序中的用户空间进程,或者从系统调用返回时。

  

当调用getpid()时,将在用户空间边界上进行一些元数据传输,并进入和退出内核。那么用户空间和内核之间的不断切换也会导致一些开销吗?

是的,如果经常调用getpid(),那么开销肯定会增加。有一些方法可以避免这种简单的“getter”系统调用(如getpid()gettimeofday();在Linux下使用的一种方法是将系统调用的(已知)结果存储在特殊的内存页面中。 (这种机制称为vsyscall。)