0

0

一次系统调用开销到底有多大?

絕刀狂花

絕刀狂花

发布时间:2025-07-19 11:20:33

|

1059人浏览过

|

来源于php中文网

原创

我们经常听说系统调用的开销比函数调用大得多,因此需要尽量减少系统调用的次数来提高代码性能。那么,系统调用的具体开销是多少呢?它需要消耗多少cpu时间?

1

系统调用概述

系统调用是用户程序与内核进行交互的机制。当代码需要进行I/O操作(如open、read、write)、内存操作(如mmap、sbrk)或获取网络数据时,必须通过系统调用来实现。无论你使用的是什么编程语言,如PHP、C、Java还是Go,只要你的程序运行在Linux内核上,就无法避免系统调用。

一次系统调用开销到底有多大?图1 系统调用在计算机系统中的位置

你可以使用strace命令查看程序正在执行的系统调用。例如,查看一个在生产环境中运行的nginx的系统调用情况如下(可能需要左右滑动查看完整内容):

# strace -p 28927
Process 28927 attached
epoll_wait(6, {{EPOLLIN, {u32=96829456, u64=140312383422480}}}, 512, -1) = 1
accept4(8, {sa_family=AF_INET, sin_port=htons(55465), sin_addr=inet_addr("10.143.52.149")}, [16], SOCK_NONBLOCK) = 13
epoll_ctl(6, EPOLL_CTL_ADD, 13, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u32=96841984, u64=140312383435008}}) = 0
epoll_wait(6, {{EPOLLIN, {u32=96841984, u64=140312383435008}}}, 512, 60000) = 1

2

使用strace命令进行实验

通过对线上运行的nginx进行strace统计,我们可以看到系统调用的耗时大约在1-15微秒(μs)之间。因此,可以得出系统调用的耗时通常在微秒级别。当然,由于不同系统调用执行的操作和环境不同,耗时会有所波动(可能需要左右滑动查看完整内容)。

# strace -cp 8527
strace: Process 8527 attached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 44.44    0.000727          12        63           epoll_wait
 27.63    0.000452          13        34           sendto
 10.39    0.000170           7        25        21 accept4
  5.68    0.000093           8        12           write
  5.20    0.000085           2        38           recvfrom
  4.10    0.000067          17         4           writev
  2.26    0.000037           9         4           close
  0.31    0.000005           1         4           epoll_ctl

3

使用time命令进行实验

我们手动编写一段代码来测试read系统调用,代码如下:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
<p>int main() {
char    c;
int     in;
int     i;</p><pre class="brush:php;toolbar:false;"><code>in = open("in.txt", O_RDONLY);
for(i=0; i<1000000; i++) {
    read(in, &c, 1);
}
close(in);
return 0;

}

注意,只能使用read库函数进行测试,不要使用fread,因为fread是用户态库函数,带有缓存,而read每次调用都会触发一次系统调用。

首先,创建一个大小为1MB的文件:

dd if=/dev/zero of=in.txt bs=1M count=1

然后编译并运行代码进行测试:

# gcc main.c -o main</p><h1>time ./main</h1><p>real    0m0.258s
user    0m0.030s
sys     0m0.227s

由于上述实验循环了100万次,因此平均每次系统调用的耗时大约为200纳秒(ns)左右。

BJXSHOP网上购物系统 - 书店版
BJXSHOP网上购物系统 - 书店版

BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录

下载

4

使用Perf命令查看系统调用消耗的CPU指令数

x86-64 CPU具有特权级别的概念。内核运行在最高级别(Ring0),用户程序运行在Ring3。当用户态程序需要访问磁盘等外设时,必须通过系统调用进行特权级别的切换。

普通函数调用通常只需要几次寄存器操作和用户栈操作,而系统调用则需要从用户态切换到内核态,涉及到内核栈和寄存器的切换,如SS、ESP、EFLAGS、CS和EIP寄存器。此外,系统调用还可能导致缓存和TLB页表缓存的命中率下降,并需要进行权限校验和有效性检查。因此,系统调用的开销远大于函数调用。

我们使用perf命令计算每个系统调用需要执行的CPU指令数(可能需要左右滑动查看完整内容):

# perf stat ./main
Performance counter stats for './main':
251.508810 task-clock                #    0.997 CPUs utilized
1 context-switches          #    0.000 M/sec
1 CPU-migrations            #    0.000 M/sec
97 page-faults               #    0.000 M/sec
600,644,444 cycles                    #    2.388 GHz                     [83.38%]
122,000,095 stalled-cycles-frontend   #   20.31% frontend cycles idle    [83.33%]
45,707,976 stalled-cycles-backend    #    7.61% backend  cycles idle    [66.66%]
1,008,492,870 instructions              #    1.68  insns per cycle         #    0.12  stalled cycles per insn [83.33%]
177,244,889 branches                  #  704.726 M/sec                   [83.32%]
7,583 branch-misses             #    0.00% of all branches         [83.33%]

将for循环中的read调用注释掉后,再次编译并运行:

# gcc main.c -o main</p><h1>perf stat ./main</h1><p>Performance counter stats for './main':
3.196978 task-clock                #    0.893 CPUs utilized
0 context-switches          #    0.000 M/sec
0 CPU-migrations            #    0.000 M/sec
98 page-faults               #    0.031 M/sec
7,616,703 cycles                    #    2.382 GHz                       [68.92%]
5,397,528 stalled-cycles-frontend   #   70.86% frontend cycles idle      [68.85%]
1,574,438 stalled-cycles-backend    #   20.67% backend  cycles idle
3,359,090 instructions              #    0.44  insns per cycle           #    1.61  stalled cycles per insn
1,066,900 branches                  #  333.721 M/sec
799 branch-misses             #    0.07% of all branches           [80.14%]
0.003578966 seconds time elapsed

平均每次系统调用需要执行的CPU指令数为(1,008,492,870 - 3,359,090)/1000000 ≈ 1005条指令。

5

深挖系统调用实现

如果你想了解系统调用的具体实现,可以参考《深入理解LINUX内核-第十章系统调用》。最初,系统调用通过汇编指令int(中断)实现,当用户态进程发出int $0x80指令时,CPU切换到内核态并执行system_call函数。后来,Intel提供了“快速系统调用”指令sysenter以提高效率。我们通过实验验证如下(可能需要左右滑动查看完整内容):

# perf stat -e syscalls:sys_enter_read ./main
Performance counter stats for './main':
1,000,001 syscalls:sys_enter_read
0.006269041 seconds time elapsed

上述实验证明,系统调用确实是通过sys_enter指令进行的。

6

结论

与函数调用不到1纳秒的耗时相比,系统调用的开销确实较大。尽管使用了“快速系统调用”指令,但耗时仍在200纳秒以上,某些情况下可能达到十几微秒。每次系统调用需要执行约1000条CPU指令,因此确实应该尽量减少系统调用次数。然而,即使是10微秒,也仅是1毫秒的百分之一,所以不必过分担心系统调用的开销。

系统调用之间耗时差异较大的原因在于,虽然内核态与用户态的切换时间基本相同,但不同的系统调用在内核态的处理工作不同,导致在内核态停留的时间差异较大。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
nginx 重启
nginx 重启

nginx重启对于网站的运维来说是非常重要的,根据不同的需求,可以选择简单重启、平滑重启或定时重启等方式。本专题为大家提供nginx重启的相关的文章、下载、课程内容,供大家免费下载体验。

245

2023.07.27

nginx 配置详解
nginx 配置详解

Nginx的配置是指设置和调整Nginx服务器的行为和功能的过程。通过配置文件,可以定义虚拟主机、HTTP请求处理、反向代理、缓存和负载均衡等功能。Nginx的配置语法简洁而强大,允许管理员根据自己的需要进行灵活的调整。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

520

2023.08.04

nginx配置详解
nginx配置详解

NGINX与其他服务类似,因为它具有以特定格式编写的基于文本的配置文件。本专题为大家提供nginx配置相关的文章,大家可以免费学习。

588

2023.08.04

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

244

2024.02.23

nginx报404怎么解决
nginx报404怎么解决

当访问 nginx 网页服务器时遇到 404 错误,表明服务器无法找到请求资源,可以通过以下步骤解决:1. 检查文件是否存在且路径正确;2. 检查文件权限并更改为 644 或 755;3. 检查 nginx 配置,确保根目录设置正确、没有冲突配置等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

651

2024.07.09

Nginx报404错误解决方法
Nginx报404错误解决方法

解决方法:只需要加上这段配置:try_files $uri $uri/ /index.html;即可。想了解更多Nginx的相关内容,可以阅读本专题下面的文章。

3613

2024.08.07

nginx部署php项目教程汇总
nginx部署php项目教程汇总

本专题整合了nginx部署php项目教程汇总,阅读专题下面的文章了解更多详细内容。

53

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

70

2026.01.13

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

4

2026.03.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 10.2万人学习

Git 教程
Git 教程

共21课时 | 4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号