我刚刚开始研究系统调用。我想知道当进行系统调用时是什么导致了开销。
例如,如果我们考虑getpid(),当系统调用getpid()时,我的猜测是,如果控件当前位于子进程中,则必须进行上下文切换才能进入父进程以获取pid。这会导致间接费用吗?
此外,当调用getpid()时,会有一些元数据跨用户空间边界传输,并进入和退出内核。那么,用户空间和内核之间的不断切换也会导致一些开销吗?
请原谅泛化(而不是限定每个句子)。
对系统服务的调用(例如返回流程信息)具有用户模式shell。这个shell触发一个异常,该异常通过调用内核模式系统服务的系统调度表进行路由。
切换到内核模式需要类似于进程上下文切换的东西。例如,它需要从用户堆栈更改为kern堆栈(以及其他依赖于系统的更改)。
调用进程提供用户模式返回缓冲区。出于安全目的,系统系统服务将在写入响应数据之前检查以确保它是有效的用户模式缓冲区。
像getpid这样只返回当前进程信息的库函数可能不需要切换到内核模式。
例如,如果我们考虑getpid(),当系统调用getpid()时,我的猜测是,如果控件当前位于子进程中,则必须进行上下文切换才能进入父进程以获取pid。
这里不需要对子进程的上下文切换——内核应该拥有所有必要的数据。在大多数情况下,内核只会将上下文切换到调度程序中的用户空间进程,或者从系统调用返回时。
同样当调用getpid()时,会有一些元数据跨越用户空间边界的传输,进入和退出内核,那么用户空间和内核之间的不断切换是否也会造成一些开销呢?
是的,如果经常调用getpid(),开销肯定会增加。有一些方法可以避免简单的“getter”系统调用的这种开销,如getpid()
和gettimeofday()
;在Linux下使用的一种方法是将系统调用的(已知)结果存储在一个特殊的内存页中。(此机制称为vsyscall。)
我在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对(
https://softwareengineering.stackexchange.com/questions/311165/why-isnt-there-generic-batching-syscall-in-linux-bsd/350173对如何最小化系统调用开销有一些有趣的想法。
本章描述 Linux 内核中的系统调用概念。 系统调用概念简介 - 介绍 Linux 内核中的系统调用概念 Linux 内核如何处理系统调用 - 介绍 Linux 内核如何处理来自于用户空间应用的系统调用。 vsyscall and vDSO - 介绍 vsyscall 和 vDSO 概念。 Linux 内核如何运行程序 - 介绍一个程序的启动过程。 open 系统调用的实现 - 介绍 open
我一直在寻找一种合适的方法来衡量Linux操作系统中各种系统调用的成本。过去有许多与此主题相关的问题,没有一个提供如何准确测量的详细描述。大多数答案都武断地宣称,系统调用的成本为1-2us,如果它在CPU上缓存,则为100个周期。 系统调用开销 系统开销 我能想到的测量系统调用成本的天真方法是在getpid()等系统调用中使用rdtscp指令。然而,这不足以准确测量open()、read()或wr
系统调用sendfile Sendfile是Linux实现的系统调用,可以通过避免文件在内核态和用户态的拷贝来优化文件传输的效率。 其中大名鼎鼎的分布式消息队列服务Kafka就使用sendfile来优化效率,具体用法可参见其官方文档。 优化策略 在普通进程中,要从磁盘拷贝数据到网络,其实是需要通过系统调用,进程也会反复在用户态和内核态切换,频繁的数据传输在此有效率问题。因此我们必须意识到Linux
系统调用 我们要想启动一个进程,需要操作系统的调用(system call)。实际上操作系统和普通进程是运行在不同空间上的,操作系统进程运行在内核态(todo: kernel space),开发者运行的进程运行在用户态(todo: user space),这样有效规避了用户程序破坏系统的可能。 如果用户态进程想执行内核态的操作,只能通过系统调用了。Linux提供了超多系统调用函数,我们关注与进程相
11.3.1 默认的调用规范 通常, FreeBSD 的内核使用 C 语言的调用规范。 此外, 虽然我们使用 int 80h 来访问内核, 但是我们常常通过调用一个函数来执行 int 80h, 而不是直接访问。 这个规范是非常方便的, 比 Microsoft® 的 MS-DOS® 上使用的规范更加优越。 为什么呢? 因为 UNIX® 的规范允许任何语言所写的程序访问内核。 汇编语言也可以这样做,
问题内容: 我可以使用什么来调用操作系统以在用户默认使用的任何浏览器中打开URL?不担心跨操作系统的兼容性;如果它在Linux上足够对我而言! 问题答案: 以下是使用给定URL打开用户默认浏览器的方法: 这是有关此功能的文档。它是Python stdlibs的一部分: http://docs.python.org/library/webbrowser.html 我已经在Linux Ubuntu 1