什么是系统调用?

发布时间 - 2025-06-26 00:00:00    点击率:

在探讨系统调用(system call)时,我们首先想到的可能是软中断、内核态和用户态。让我们从头开始,重新理解“系统调用”这个概念。

实际上,系统调用这个术语有两种解释。一些资料将open、read、write、fork等man手册第二页的函数称为系统调用,但实际上这些只是真正系统调用的封装函数(wrapper functions),我称之为广义上的系统调用。这些封装函数通过软中断陷入内核态,然后调用对应的真正的系统调用,通常是一一对应的。例如,fork函数内部会调用sys_fork,而后者才是严格意义上的系统调用,由内核提供的服务,我称之为狭义的系统调用。

系统调用的封装函数是由glibc实现的,而真正的系统调用是由内核实现的。你可能觉得这有点复杂,让我们看一下epoll的man手册,其末尾有一个版本声明:

翻译过来就是,Linux内核的2.5.44版本引入了epoll,而glibc的2.3.2版本开始支持epoll。

这里特别提到glibc的版本,是为了说明即使你的Linux内核版本支持epoll系统调用,但如果你的glibc版本不够,你仍然无法直接使用以epoll开头的那些函数。为什么需要glibc封装一层呢?主要是因为系统调用在实际调用时涉及到一些汇编指令(后文会详细介绍)。

尽管我已经解释了系统调用的两种理解,但还有一点需要注意:(广义上的)系统调用的具体实现与内核架构有关。我上述描述的过程主要基于Linux,但纵观整个Unix-like操作系统家族,实际上还有不同的声音。这就引出了单内核与微内核之争。

单内核与微内核的争论始于1992年,由国外的谭宁邦教授(Tanenbaum)和Linux的发明者林纳斯(Linus)展开。当时林纳斯还是一个刚崭露头角的小伙子,一年前他曾在校园网上发布了Linux内核。

单内核(Monolithic kernel),也称为宏内核,但我认为宏内核这个词可能会引起误解,所以我将一直使用单内核这个术语。Linux就是基于单内核的,这是较为传统的内核架构。内核提供多种服务,我们常用的文件IO、内存管理、网络相关的系统调用都在内核态运行,且都在同一地址空间内。

谭宁邦教授直言Linux采用单内核是在开历史倒车,是操作系统技术的倒退,回到七十年代。此前他也曾开源一个类Unix的操作系统,名为MINIX,而MINIX基于微内核。

微内核(Microkernel)提出时间比单内核晚,在学术界被视为新兴的技术。微内核采用模块化设计,将内核功能简化到最少,只提供基本功能,更多的功能在用户态运行,不同服务在不同地址空间运行,常用服务(如IO、内存管理)通过IPC调用组合提供。从这个角度看,微内核的扩展性更强,添加新功能无需重新编译内核,且由于内核服务间的隔离,使得操作系统更安全,一个服务崩溃不会影响其他服务。但问题也很明显,大量的IPC会影响性能。

微内核的理念与后来大型分布式系统中的SOA、微服务概念不谋而合。然而,历史并未如期发展,站在二十一世纪的第三个十年回望,Linux取得了空前的成功。时至今日,无论是MINIX还是其他,鲜有广泛使用的微内核操作系统(去年华为鸿蒙高调宣布采用单微内核架构,我们拭目以待)。当然,Linux的成功与其采用单内核架构并无直接关联,主要归功于其出色的开源社区运营模式(观点出自《大教堂与集市》)。

谭宁邦教授和林纳斯的这场论战在上世纪90年代引起了巨大反响,双方阵营都有多位技术大牛加入讨论。这场论战的记录至今仍常见诸报端。论战持续时间很长,从技术本身的争辩到后来双方的互相呛声,多年后两人也曾公开表达和解,表示双方只是技术之争,不涉及任何私人攻击。

在这场论战之前,这位老教授和这位年轻的发明者其实也有交集。谭宁邦教授曾出版过讲解Unix和操作系统的书籍,并随书附赠了MINIX的源码。林纳斯在发明Linux之前,确实通过这本书和MINIX的代码学习了操作系统知识。所以从某种意义上说,谭宁邦教授可以说是林纳斯的半个老师。

这场论战距今已近三十年,是争是吵,已无需纠结。这里不再展开具体细节,有兴趣的读者可以在互联网上找到当年的蛛丝马迹。

内核态、用户态与CPU的特权等级Intel x86 CPU的架构将所运行的指令划分为4个不同特权等级:ring 0、ring 1、ring 2、ring 3,通常称为保护环(protection ring)。从ring 0到ring 3,特权级别依次降低。Linux使用了ring 0和ring 3两个特权等级。运行在ring 0的程序被称为内核态(Kernel Space)程序,运行在ring 3的程序被称为用户态(User Space)程序。

图片来自网络

系统调用与软中断我们已经大致了解了什么是用户态,什么是内核态。那么,这与系统调用有什么关系呢?

请看下一张图:

图片来自网络

可以看到,在用户态和内核态的边界上画着线,这就是系统调用!也就是说,无论是单内核还是微内核,运行在用户态的应用程序想要使用某些只能在内核态执行的功能,必须通过系统调用来实现。所以你需要明白:进程从用户态陷入内核态是目的,而使用系统调用仅仅是达到该目的的手段。因果关系要理清楚。

接下来解释一下什么是软中断。要说软中断,先说一下中断(interrupt),如果你大学时学过《计算机组成与体系结构》这门课,你应该会记得。中断本身是一个硬件概念,就是打断CPU,让其执行其他任务,比如键盘中断、打印机中断、定时器中断等。软中断则是从软件层面模拟了这一中断操作。

网上许多资料会提到使用128号软中断指令(int 0x80)来使进程从用户态陷入内核态,执行完毕后使用iret指令返回用户态。但这是较为传统的老方法。随着CPU(Intel和AMD)的升级,Linux内核通常使用快速系统调用(Fast system calls)的sysenter/syscall指令代替int 0x80,使用sysexit/sysret代替iret。在运行软中断指令时,会使用一个寄存器来存储具体的系统调用号,例如在Linux上,read和write的系统调用号分别为0和1。

单内核与微内核上的系统调用有什么不同呢?就系统调用的实现原理而言,没有不同。所谓的差异实际上体现在系统调用的封装函数的种类上!前面提到,单内核内核提供许多服务。以Linux为代表,其系统调用种类繁多,有三百多种。可以查看:filippo.io/linux-syscal

而微内核操作系统,则没有这么多系统调用。例如,MINIX实际上只有三个系统调用(的封装函数):

发送:_send()接收:_receive()发收一体:_sendrec()(基于老版本MINIX,最新的MINIX是否扩展了尚不清楚)

这当然不是说MINIX不支持open()、read()、write()和fork()。只是在MINIX系统上,这些功能本质上都是通过_send()、_receive()、_sendrec()实现的。所以准确来说,MINIX上与Linux的open()、read()、write()、fork()这些系统调用封装函数对应的,是_send()、_receive()、_sendrec()。


# windows  # linux  # 操作系统  # 鸿蒙  # 为什么  # 架构  # 分布式  # 封装  # int  # unix  # 这场  # 纳斯  # 这是  # 让我们  # 是由  # 被称为  # 之争  # 网上  # 保护环 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何用好域名打造高点击率的自主建站?  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  Python高阶函数应用_函数作为参数说明【指导】  如何快速查询网址的建站时间与历史轨迹?  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  韩国服务器如何优化跨境访问实现高效连接?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  javascript如何操作浏览器历史记录_怎样实现无刷新导航  简历没回改:利用AI润色让你的文字更专业  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  Python进程池调度策略_任务分发说明【指导】  b2c电商网站制作流程,b2c水平综合的电商平台?  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  Laravel怎么为数据库表字段添加索引以优化查询  Laravel Octane如何提升性能_使用Laravel Octane加速你的应用  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  Android中AutoCompleteTextView自动提示  北京专业网站制作设计师招聘,北京白云观官方网站?  HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】  在线教育网站制作平台,山西立德教育官网?  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  进行网站优化必须要坚持的四大原则  Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试  如何用腾讯建站主机快速创建免费网站?  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  什么是javascript作用域_全局和局部作用域有什么区别?  如何在景安服务器上快速搭建个人网站?  canvas 画布在主流浏览器中的尺寸限制详细介绍  Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  高性价比服务器租赁——企业级配置与24小时运维服务  网站制作软件有哪些,制图软件有哪些?  网站页面设计需要考虑到这些问题  Laravel怎么判断请求类型_Laravel Request isMethod用法  php做exe能调用系统命令吗_执行cmd指令实现方式【详解】  如何快速生成高效建站系统源代码?  Python正则表达式进阶教程_复杂匹配与分组替换解析  Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】  javascript中的数组方法有哪些_如何利用数组方法简化数据处理