0

0

Linux系统调用如何工作_用户态与内核态解析【指导】

舞姬之光

舞姬之光

发布时间:2026-01-08 20:45:10

|

995人浏览过

|

来源于php中文网

原创

系统调用是通过软中断或syscall指令触发的特权态切换,而非普通函数调用;用户态经int 0x80或syscall陷入内核态,切换栈、保存上下文、查表执行对应内核函数,glibc仅做封装与错误处理。

linux系统调用如何工作_用户态与内核态解析【指导】

系统调用不是函数调用,是软中断触发的特权切换

用户程序调用 open()read() 这类“函数”时,实际执行的不是内核代码,而是 glibc 提供的封装——它最终通过 int 0x80(x86)或 syscall 指令(x86-64)主动陷入内核。这个过程强制 CPU 从用户态(ring 3)切到内核态(ring 0),并跳转到预设的中断处理入口。

关键点在于:用户被保留但不再可用;CPU 切换到内核栈;寄存器上下文被保存;内核根据传入的系统调用号(如 __NR_read = 0)查表找到对应内核函数(如 sys_read)。

  • glibc 封装会做参数校验、错误码转换(-1errno),但不参与真正的 I/O 或内存管理
  • 直接写汇编调用 syscall 指令绕过 libc 是可行的,但需手动设置 %rax(调用号)、%rdi/%rsi/%rdx(参数),且失去可移植性
  • 现代 x86-64 推荐用 syscall 指令而非 int 0x80,后者在 64 位下可能截断指针或触发兼容模式开销

用户态和内核态的内存隔离靠页表和 CR0.WP 位保障

Linux 使用分页机制实现地址空间隔离:每个进程有独立的页表,用户态只能访问标记为 “user accessible” 的页表项(PT_USER 位)。当 CPU 处于用户态时,若尝试访问内核地址(如 0xffff888000000000 起始的直接映射区),会触发 #PF(page fault)异常,由内核的缺页处理程序拦截并终止进程。

内核自身也受保护:CR0 寄存器的 WP(Write Protect)位开启后,即使在内核态,对只读页(如代码段、常量数据)的写操作也会触发异常——这防止了模块或驱动意外覆写内核关键结构。

  • copy_to_user()copy_from_user() 不是简单 memcpy,它们会先用 access_ok() 检查地址是否落在当前进程的用户地址空间范围内,再逐页检查页表权限
  • 用户传入的指针(如 buf 参数)必须是当前进程虚拟地址空间内的有效地址;传入内核地址(如 &some_kernel_var)会导致 -EFAULT
  • 内核态不能直接使用用户栈,所有系统调用入口都会立即切换到 per-CPU 内核栈(通常 16KB),避免栈溢出影响内核稳定性

strace 看到的 read(3, "...", 1024) 实际经历了三次上下文切换

运行 strace -e trace=read ./a.out 显示一行 read(3, "hello\n", 1024) = 6,但这背后至少发生三次 CPU 特权级切换:

四维时代AI开放平台
四维时代AI开放平台

四维时代AI开放平台

下载
user: call read() → enter kernel (1st switch)
kernel: do_syscall_64() → sys_read() → vfs_read() → ... → copy_to_user()
kernel: 返回前准备用户寄存器、恢复用户栈指针 → exit_to_user_mode() (2nd switch)
user: read() 返回,但此时仍处于用户态;若后续有信号待投递,会再陷入内核处理(3rd switch)

每次切换涉及寄存器保存/恢复、TLB 刷新(部分架构)、栈切换,开销远高于普通函数调用。频繁小读写(如循环调用 read(fd, &c, 1))性能极差,本质是把 I/O 变成了系统调用风暴。

  • 系统调用号本身不跨架构:x86-64 的 __NR_read 是 0,arm64 也是 0,但寄存器传参约定不同(arm64 用 x0~x7
  • strace 依赖 ptrace(PTRACE_SYSCALL) 在每次进入/退出系统调用时暂停目标进程,因此本身会显著拖慢被跟踪程序
  • 真正零拷贝路径(如 splice()io_uring)的目标就是减少甚至消除用户/内核间的数据拷贝和上下文切换次数

自定义系统调用为什么现在几乎没人做

添加新系统调用需修改内核源码(arch/x86/entry/syscalls/syscall_table_64.c)、分配唯一调用号、提供稳定 ABI,并面临上游拒绝合入的风险。相比而言,字符设备驱动 + ioctl()、eBPF 程序、用户态协议栈(如 DPDK)、或 io_uring 提供的扩展接口更安全、灵活、无需重启内核。

  • 新增系统调用一旦合入主线,就必须永久维护 ABI 兼容性,连参数语义都不能变——比如 stat() 的 struct layout 锁死几十年
  • Android 的 binder、Chrome OS 的 minijail 都没加新 syscall,而是基于现有机制(ioctlseccompmemfd_create)构建
  • 真正需要内核介入的新功能(如 cgroup v2、landlock)都走 netlink、procfs、sysfs 等已有通道,而非塞进 syscall 表

用户态和内核态的边界清晰,但跨越它的成本比想象中高;多数优化方向不是“让系统调用更快”,而是“少调用几次”。

相关专题

更多
chrome什么意思
chrome什么意思

chrome是浏览器的意思,由Google开发的网络浏览器,它在2008年首次发布,并迅速成为全球最受欢迎的浏览器之一。本专题为大家提供chrome相关的文章、下载、课程内容,供大家免费下载体验。

763

2023.08.11

chrome无法加载插件怎么办
chrome无法加载插件怎么办

chrome无法加载插件可以通过检查插件是否已正确安装、禁用和启用插件、清除插件缓存、更新浏览器和插件、检查网络连接和尝试在隐身模式下加载插件方法解决。更多关于chrome相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

726

2023.11.06

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

531

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

50

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1007

2023.10.19

php学习网站大全
php学习网站大全

精选多个优质PHP入门学习网站,涵盖教程、实战与文档,适合零基础到进阶开发者,助你高效掌握PHP编程。

0

2026.01.09

热门下载

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

精品课程

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

共48课时 | 6.8万人学习

Git 教程
Git 教程

共21课时 | 2.5万人学习

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

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