Process 系统调用开销
我刚开始研究系统调用。 我想知道在进行系统调用时,是什么导致开销 比如说,, 如果我们考虑GETPIDE(),当系统调用是GETPIDE()时,我猜想如果控制当前在子进程中,那么必须进行上下文切换来进入父进程以获得PID。这会导致开销增加吗 另外,当调用getpid()时,会有一些元数据跨用户空间边界传输,并进入和退出内核。因此,用户空间和内核之间的不断切换也会导致一些开销吗Process 系统调用开销,process,operating-system,system-calls,context-switch,os161,Process,Operating System,System Calls,Context Switch,Os161,我刚开始研究系统调用。 我想知道在进行系统调用时,是什么导致开销 比如说,, 如果我们考虑GETPIDE(),当系统调用是GETPIDE()时,我猜想如果控制当前在子进程中,那么必须进行上下文切换来进入父进程以获得PID。这会导致开销增加吗 另外,当调用getpid()时,会有一些元数据跨用户空间边界传输,并进入和退出内核。因此,用户空间和内核之间的不断切换也会导致一些开销吗 例如,如果我们考虑GETPID.(),当系统调用被调用到GETPID.()时,我猜想如果控件当前在子进程中,那么必须进行
例如,如果我们考虑GETPID.(),当系统调用被调用到GETPID.()时,我猜想如果控件当前在子进程中,那么必须进行上下文切换来进入父进程以获得PID。 这里不需要切换到子进程的上下文-内核本身应该拥有所有必要的数据。在大多数情况下,内核只会在调度器中或从系统调用返回时将上下文切换到用户空间进程
另外,当调用getpid()时,会有一些元数据跨用户空间边界传输,并进入和退出内核。那么,用户空间和内核之间的不断切换也会导致一些开销吗 是的,如果经常调用getpid()
,开销肯定会增加。对于简单的“getter”系统调用,有一些方法可以避免这种开销,如getpid()
和gettimeofday()
;在Linux下使用的一种方法是将系统调用的(已知)结果存储在一个特殊的内存页中。(这种机制被称为。)请原谅泛化(而不是限定每个句子)
对系统服务的调用(例如返回进程信息)具有用户模式外壳。这个shell触发一个异常,该异常通过调用内核模式系统服务的系统调度表进行路由
切换到内核模式需要类似于进程上下文切换的东西。例如,它需要从用户堆栈更改为内核堆栈(以及其他依赖于系统的更改)
调用进程提供一个用户模式返回缓冲区。为了安全起见,在写入响应数据之前,系统服务将检查以确保它是有效的用户模式缓冲区
像getpid这样只返回当前进程信息的库函数可能不需要切换到内核模式。我在x86-64 Linux(使用-O3编译)上做了一些更精确的基准测试: 最便宜的“系统调用”是通过辅助向量(~20–30ns)的调用。中间调用(250~310NS)最准确地反映了平均开销,因为在内核中不应该有太多的工作要做。 相比之下,malloc+免费对的小规模请求(无系统调用)成本约为70-80ns(请参阅我的答案)
对于如何最小化系统调用开销有一些有趣的想法。
getpid()
是从glibc 2.25开始的,该版本在提交此答案后不久发布。的手册页提供了有关该主题的一些附加上下文,并指出缓存是从2.3.4版到2.24版提供的。常规函数是系统调用还是普通函数?@scottxiao regular=commongeteuid
是真正的系统调用开始的地方。一个真正的系统调用不会比这快很多。
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