0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

探索操作系统底层的关键接口

来源:jf_57394773 2025-11-08 12:42 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、前言

为什么用户程序不能直接访问系统内核模式提供的服务?

linux中,将程序的运行空间分为内核空间与用户空间(内核态和用户态),在逻辑上它们之间是相互隔离的,因此用户程序不能访问内核数据,也无法使用内核函数。当用户进程必须访问内核或使用某个内核函数时,就得使用系统调用(System Call)。在Linux中,系统调用是用户空间访问内核空间的唯一途径。

什么是系统调用?

答:系统调用就是一种特殊的接口。通过这个接口,用户可以访问内核空间。系统调用规定了用户进程进入内核的具体位置。系统调用是用户进程进入内核的接口层,它本身并非内核函数,但它是由内核函数实现,进入内核后,不同的系统调用会找到各自对应的内核函数,这些内核函数被称为系统调用的“服务例程”。比如系统调用getpid实际调用了服务例程为sys_getpid(),或者说系统调用getpid是服务例程sys_getpid()的“封装例程”。

具体步骤:用户进程-->系统调用-->内核-->返回用户空间。

系统调用就是为了解决上述问题而引入的,是提供给用户的“特殊接口”,系统调用规定用户进程进入内核空间的具体位置。

1.程序运行空间从用户空间进入内核空间。

2.处理完后再返回用户空间。

什么是API

答:应用程序接口API(Application Programming Interface) ,是程序员在用户空间下可以直接使用的函数接口。是一些预定义的函数,比如常用的read()、malloc()、free()、abs()函数等,这些函数都具有一定功能,说明了如何获得一个给定的服务,跟内核没有必然的联系。提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

两者的区别

答:区别:api是函数的定义,规定了这个函数的功能,跟内核无直接关系。而系统调用是通过中断向内核发请求,实现内核提供的某些服务。

联系:程序员调用的是API(API函数),然后通过与系统调用共同完成函数的功能。 因此,API是一个提供给应用程序的接口,一组函数,是与程序员进行直接交互的。系统调用则不与程序员进行交互的,它是根据API函数,通过一个软中断机制向内核提交请求,以获取内核服务的接口。

有时候,某些API所提供的功能会涉及到与内核空间进行交互。那么,这类API内部会封装系统调用。而不涉及与内核进行交互的API则不会封装系统调用。也就是说,API和系统调用并没有严格的一一对应关系,一个API可能恰好只对应一个系统调用,比如read()系统调用和read();一个API也可能由多个系统调用实现;有时候,一个API的功能可能并不需要内核提供的服务,那么此时这个API也就不需要任何的系统调用,比如abs()。另外,一个系统调用可能还被多个API内部调用。

对于编程者来说,系统调用和API都是一组函数,并无什么两样,二者关注的都是函数名、参数类型及返回值的含义;但是事实上,系统调用的实现是在内核完成的,API则是在函数库中实现的。

例如: 在内核中实现了write系统调用。

AI写代码

在库函数中通过宏定义的方式实现write API。可以在unistd.h中看到write到系统调用的转换。

API是用户程序直接可以使用的函数接口,但如果每个操作系统都拥有只属于自己的API,那么应用程序的移植性将会很差。基于POSIX(Portable Operating System Interface)标准的API拥有很好的可移植性,它定义了一套POSIX兼容标准,这使得按这个标准实现的API可以在各种版本的UNIX中使用。现如今,它也可以在除UNIX之外的操作系统中使用,比如Linux,Windows NT等。

二、系统调用

操作系统负责管理和分配所有的计算机资源。为了更好地服务于应用程序,操作系统提供了一组特殊接口———系统调用。用户程序可以通过这组特殊的接口来获取操作系统内核提供的各种功能,如分配内存、创建进程、实现进程之间的通信等。

系统调用(system call) 其实是 Linux 内核提供给应用层的应用编程接口(API) , 是 Linux 应用层进入内核的入口。不止 Linux 系统,所有的操作系统都会向应用层提供系统调用,应用程序通过系统调用来使用操作系统提供的各种服务。

通过系统调用, Linux 应用程序可以请求内核以自己的名义执行某些事情,譬如打开磁盘中的文件、读写文件、关闭文件以及控制其它硬件外设。

通过系统调用 API,应用层可以实现与内核的交互,其关系可通过下图简单描述:

内核提供了一系列的服务、资源、支持一系列功能,应用程序通过调用系统调用 API 函数来使用内核提供的服务、资源以及各种各样的功能, 如果大家接触过其它操作系统编程,想必对此并不陌生,譬如Windows 应用编程,操作系统内核一般都会向应用程序提供应用编程接口 API,否则我们将我无法使用操作系统。

为什么用户程序不能直接访问系统内核提供的服务呢?答案是不安全。

单片机开发中,由于不需要操作系统,只需要知道寄存器的地址,代码通过指针直接操作硬件,所以开发人员可以编写代码直接访问硬件。硬件>>>>>>代码直接在内存中运行操作硬件。

而在嵌入式系统中通常都要运行操作系统,程序访问资源的方式就发生了改变。操作系统基本上都支持多任务,即同时可以运行多个程序。如果允许程序直接访问系统资源,肯定会带来很多问题。因此,所有软硬件资源的管理和分配都由操作系统负责。程序要获取资源(如分配内存、读写串口)必须通过操作系统来完成,即用户程序向操作系统发出服务请求,操作系统收到请求后执行相关的代码来处理。硬件>>>>>>>操作系统>>>>>>>代码

还有更重要的一点是,在Linux中,为了更好地保护内核空间,将程序的运行空间分为用户空间和内核空间(也就是常称的用户态和内核态),它们分别运行在不同的级别上,逻辑上是相互分离的。因此,用户进程通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间的函数。但是,在有些情况下,用户空间的进程需要获得内核的系统服务(调用内核空间程序),这时操作系统就必须利用系统提供用户的特殊接口———”系统调用”规定用户进程进入内核空间的具体位置。在进行系统调用时,程序运行空间需要从用户空间进入内核空间,处理完成后再返回用户空间。

用户程序向操作系统提出请求的接口就是系统调用。所有的操作系统都会提供系统调用接口,只不过不同的操作系统提供的系统调用接口各不相同。Linux系统调用接口非常精简(只有250个左右),它继承了UNIX系统调用中最基本和最有用的部分。这些系统调用按照功能大致可分为进程控制、进程间通信、文件系统控制、存储管理、网络管理、套接字控制、用户管理等。

应用编程与裸机编程、驱动编程有什么区别?

在学习应用编程之前,相信大家都有过软件开发经验,譬如 51、 STM32单片机软件开发、 以及嵌入式 Linux 硬件平台下的驱动开发等, 51、 STM32 这类单片机的软件开发通常是裸机程序开发,并不会涉及到操作系统的概念,那应用编程与裸机编程以及驱动开发有什么区别呢?

就拿嵌入式 Linux 硬件平台下的软件开发来说,我们大可将编程分为三种,分别为裸机编程、 Linux 驱动编程以及 Linux 应用编程。首先对于裸机编程这个概念来说很好理解,一般把没有操作系统支持的编程环境称为裸机编程环境,譬如单片机上的编程开发,编写直接在硬件上运行的程序,没有操作系统支持; 狭义上 Linux 驱动编程指的是基于内核驱动框架开发驱动程序, 驱动开发工程师通过调用 Linux 内核提供的接口完成设备驱动的注册, 驱动程序负责底层硬件操作相关逻辑, 如果学习过 Linux 驱动开发的读者,想必对此并不陌生; 而 Linux 应用编程(系统编程)则指的是基于 Linux 操作系统的应用编程,在应用程序中通过调用系统调用 API 完成应用程序的功能和逻辑, 应用程序运行于操作系统之上。通常在操作系统下有两种不同的状态:内核态和用户态,应用程序运行在用户态、而内核则运行在内核态。

三、用户编程接口(API)---C库

前面提到利用系统调用接口程序可以访问各种资源,但并不直接与程序员进行交互,它仅仅是一个通过软中断机制向内核提交请求以获取内核服务的接口。但在实际开发中程序并不直接使用系统调用接口,而是使用用户程序编程接口(API)。例如,创建进程的API函数fork()函数对应于内核空间的sys_fork()系统调用,但并不是所有的函数都对应一个系统调用。有时,一个API函数会需要几个系统调用来共同完成函数的功能,甚至还有一些API函数不需要调用相应的系统调用(因此它所完成的不是内核提供的服务)。

前面给大家介绍了系统调用,系统调用是内核直接向应用层提供的应用编程接口, 譬如 open、 write、read、 close 等。编写应用程序除了使用系统调用之外,我们还可以使用库函数。

库函数也就是 C 语言库函数, C 语言库是应用层使用的一套函数库, 在 Linux 下,通常以动态(.so)库文件的形式提供,存放在根文件系统/lib 目录下, C 语言库函数构建于系统调用之上,也就是说库函数其实是由系统调用封装而来的,当然也不能完全这么说, 原因在于有些库函数并不调用任何系统调用,譬如一些字符串处理函数 strlen()、 strcat()、 memcpy()、 memset()、 strchr()等等; 而有些库函数则会使用系统调用来帮它完成实际的操作,譬如库函数 fopen 内部调用了系统调用 open()来帮它打开文件、库函数 fread()就利用了系统调用 read()来完成读文件操作、 fwrite()就利用了系统调用 write()来完成写文件操作。

库函数可以理解为是对系统调用的一层封装。系统调用作为内核提供给用户程序的接口,它的执行效率是比较高效而精简的,但有时我们需要对获取的信息进行更复杂的处理,或更人性化的需要,我们把这些处理过程封装成一个函数再提供给程序员,更方便于程序猿编码。库函数有可能包含有一个系统调用,有可能有好几个系统调用,当然也有可能没有系统调用,比如有些操作不需要涉及内核的功能。可以参考下图来理解库函数与系统调用的关系。

Linux 系统内核提供了一系列的系统调用供应用层使用, 我们直接使用系统调用就可以了呀,那为何还要设计出库函数呢?事实上, 有些系统调用使用起来并不是很方便, 于是就出现了 C 语言库,这些 C 语言库函数的设计是为了提供比底层系统调用更为方便、更为好用、 且更具有可移植性的调用接口。

来看一看它们之间的区别:

库函数是属于应用层,而系统调用是内核提供给应用层的编程接口,属于系统内核的一部分;

库函数运行在用户空间,调用系统调用会由用户空间(用户态)陷入到内核空间(内核态);

库函数通常是有缓存的,而系统调用是无缓存的,所以在性能、效率上,库函数通常要优于系统调用;

可移植性:库函数相比于系统调用具有更好的可移植性,通常对于不同的操作系统,其内核向应用层提供的系统调用往往都是不同,譬如系统调用的定义、功能、参数列表、返回值等往往都是不一样的;而对于 C 语言库函数来说,由于很多操作系统都实现了 C 语言库, C 语言库在不同的操作系统之间其接口定义几乎是一样的,所以库函数在不同操作系统之间相比于系统调用具有更好的可移植性。

以上便上它们之间一个大致的区别, 从实现者的角度来看,系统调用与库函数之间有根本的区别,但从用户使用角度来看,其区别并不重要,它们都是 C 语言函数。 在实际应用编程中,库函数和系统调用都会使用到,所以对于我们来说,直接把它们当做是 C 函数即可,知道你自己调用的函数是系统调用还是库函数即可,不用太过于区分它们之间的差别,所以应用编程简单点来说就是:开发 Linux 应用程序,通过调用内核提供的系统调用或使用 C 库函数来开发具有相应功能的应用程序。

为什么不直接使用系统调用接口了。原因如下:

系统调用接口功能非常简单,无法满足程序的要求

不同操作系统的系统调用接口不兼容,程序移植时工作量大。

用户程序编程接口通俗的解释就是各种库(最重要的就是C库)中的函数。为了提高开发效率,C库中实现了很多函数。这些函数实现了常用的功能,供程序员调用。这样一来,程序员就不需要自己编写这些代码。直接调用库函数就可以实现基本功能,提高了代码的复用率。使用用户程序编程接口好友一个好处就是:程序具有良好的可移植性。几乎所有的操作系统上都实现了C库,所以程序通常只需要重新编译一下就可以在其它操作系统下运行。

在Linux中,用户程序编程接口(API)遵循了UNIX中最流行的应用编程界面标准———POSIX标准。POSIX标准是由IEEE和ISO/IEC共同开发的标准系统,该标准基于当时的UNIX实践和经验,描述了操作系统的系统调用编程接口(实际上就是API),用于保证应用程序可以在源代码一级上在多种操作系统上移植运行。这些系统调用编程接口主要是通过C库(libc)实现的。

3.1系统命令

每一个系统命令其实就是一个可执行的程序,这些可执行程序的实现调用了某些系统调用。并且,这些可执行程序又分为普通用户可使用的命令和管理员可使用的命令。根据上述分类,普通用户可用的命令和管理可用的命令分别被存放于/bin和/sbin目录下。

系统命令相对于API更高了一层,它实际上是一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能,它们之间的关系如下图:

3.2内核函数

内核函数和用户空间中函数并无两样,只不过内核函数是在内核中实现。虽然系统调用是用户进程进入内核的唯一途径,但是系统调用函数内部并不真正实现其功能,而是通过对内核函数的封装。也就是说,用户程序通过某个系统调用进入内核后,会接着去执行这个系统调用对应的内核函数。这个内核函数也称为系统调用的服务例程。

由于内核函数是在内核中实现的,因此它必须符合内核编程的规则,比如函数名以sys_开始,函数定义时候需加asmlinkage标识符等。

四、标准C程序的实例

首先,C程序调用API函数printf;

printf 函数的调用引发了对应的系统调用write的执行;

write执行结束时的返回值传递回用户程序;

4.1操作系统的模式

(1)双重模式(DUAL MODE)

现代计算机系统有一个特殊的硬件,用于划分系统的运行状态,至少需要两种单独运行模式:

用户模式(user mode):执行用户代码

内核模式(kernel mode):执行操作系统代码

目的:确保操作系统正确的运行

实现方式:用一个硬件模式位来表示当前模式:0表示内核模式,1表示用户模式

(2)运行模式的切换

程序执行流刚开始在“用户模式”运行,当发生系统调用的时候,需要从“用户模式”切换到“内核模式”运行。

这种模式切换的机制称为:陷阱(Trap)机制。

4.2系统调用的实现机制

如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。

版权声明:本文为CSDN博主「xie13307907056」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/xie13307907056/article/details/154171834

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11817

    浏览量

    219552
  • 操作系统
    +关注

    关注

    37

    文章

    7437

    浏览量

    129621
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    海光信息全面适配统信桌面操作系统V25

      国产化进程正从“全面推进”向“深度攻坚”跨越,从行业应用的办公、云平台基础场景渗透至金融、能源等关键行业核心系统,聚焦“从有到优”“从优到强”的核心突破。海光信息作为底层算力领域龙头企业,与国
    的头像 发表于 04-16 09:26 585次阅读
    海光信息全面适配统信桌面<b class='flag-5'>操作系统</b>V25

    主流国产操作系统解析:技术特点与行业适配指南

    在信创产业全面推进、核心技术自主可控成为发展主线的背景下,国产操作系统已完成从技术突破到生态落地的关键跨越,形成多品牌差异化竞争的市场格局。各类操作系统依托自身技术优势,在党政、金融、能源、教育
    的头像 发表于 03-27 14:27 217次阅读

    国产工业操作系统选型指南:硬实时、功能安全与生态怎么选

    在工业4.0浪潮席卷全球、国产化替代进入深水区的今天,工业操作系统是整个工业数字生态的“底层基座”,直接决定了系统的稳定性、控制精度与安全等级。从高端数控系统到工业机器人的精准协同,再
    的头像 发表于 03-04 09:48 1125次阅读

    操作系统体系结构

    优势。   但随着体系结构和应用需求的不断发展,需要操作系统提供的服务越来越多,而且接口形式越来越复杂,操作系统的设计规模也急剧增长,操作系统也面临着“软件危机”困境。为此,
    发表于 01-15 08:19

    操作系统运行机制

    不同的层次上。一些与硬件关联较紧密的模块,诸如时钟管理、中断处理、设备驱动等处于最底层。其次是运行频率较髙的程序,诸如进程管理、存储器管理和设备管理等。这两部分内容构成了操作系统的内核。这部分内容的指令
    发表于 01-15 07:12

    什么是嵌入式操作系统

    、嵌入式操作系统的定义 嵌入式操作系统是专门为资源受限的嵌入式设备(比如 STM32 单片机、物联网模块、工业控制器)设计的微型操作系统,核心作用是:管理硬件资源、调度多任务、提供标准化接口
    发表于 12-09 10:33

    EV10AS180A模数转换器支持哪些操作系统

    基于模拟信号的采样、量化和编码,这些过程均由硬件电路完成,不涉及操作系统层面的指令或驱动。因此,该转换器本身不直接支持或依赖任何操作系统接口与通信协议:虽然EV10AS180A不直接支持操作
    发表于 11-18 09:18

    单片机的操作系统

    。 ‌ ‌ RT-Thread ‌:国产开源系统,集成GUI、网络协议栈、文件系统等组件,兼容POSIX接口,适合物联网设备。 ‌ 嵌入式操作系统 ‌ μClinux ‌:针对无M
    发表于 11-14 06:18

    深入了解系统调用API:探索操作系统底层关键接口

    ,也无法使用内核函数。当用户进程必须访问内核或使用某个内核函数时,就得使用系统调用(System Call)。在Linux中,系统调用是用户空间访问内核空间的唯一途径。 什么是系统调用? 答:
    的头像 发表于 11-03 09:20 876次阅读

    树莓派操作系统:版本、特性及设置完整指南!

    树莓派操作系统是什么?树莓派操作系统是由树莓派基金会专为树莓派开发的官方操作系统。它基于DebianLinux发行版,并针对树莓派的ARM架构进行了专门优化。树莓派操作系统有多个版本,
    的头像 发表于 07-28 18:26 1811次阅读
    树莓派<b class='flag-5'>操作系统</b>:版本、特性及设置完整指南!

    深度智能 基座跃迁 鸿道Intewell,面向“AI+智造”的新型工业操作系统

    科东软件受邀参加“数字化与智能制造技术论坛”,带来“AI+智造”的精彩分享。在“AI+智造”深度融合的时代洪流中,工业操作系统作为底层基座的重要性日益凸显。鸿道Intewell操作系统已成为驱动中国制造业智能化跃迁的
    的头像 发表于 07-23 17:02 726次阅读
    深度智能 基座跃迁  鸿道Intewell,面向“AI+智造”的新型工业<b class='flag-5'>操作系统</b>

    揭秘LuatOS:实时操作系统RTOS核心库的关键技术剖析!

    电机控制、传感器采集等实时数据处理场景。 在LuatOS开发中, 用于实时操作系统(RTOS)相关功能的核心库 ——提供了定时器管理、系统控制、内存监控、路径配置等底层操作
    的头像 发表于 05-21 16:02 791次阅读
    揭秘LuatOS:实时<b class='flag-5'>操作系统</b>RTOS核心库的<b class='flag-5'>关键</b>技术剖析!

    鸿道Intewell操作系统:人形机器人底层操作系统

    操作系统的实时性赋能东土科技的鸿道(Intewell)工业操作系统作为国内唯一通过汽车、工业控制、医疗、轨道交通四项功能安全认证的系统,为标准体系中的技术层架构提供了底层支持。其微内核
    的头像 发表于 05-16 14:44 959次阅读

    基于LuatOS核心库的实时操作系统开发:从理论到实践~

    ,降低了系统阻塞风险。 在LuatOS开发中,用于实时操作系统(RTOS)相关功能的核心库——提供了定时器管理、系统控制、内存监控、路径配置等底层
    的头像 发表于 05-16 13:56 646次阅读
    基于LuatOS核心库的实时<b class='flag-5'>操作系统</b>开发:从理论到实践~

    理想汽车智驾操作系统解读

    (HaloOS),基于“资源集中与共享、极致性能、快速迭代、高安全性”四大设计原则,打通了底层硬件与上层智能应用的隔阂,为自动驾驶技术提供了强大而可靠的系统底座。 在过去的几十年里,汽车操作系统的发展与汽车电子电气架构的演变紧
    的头像 发表于 05-13 10:54 1440次阅读
    理想汽车智驾<b class='flag-5'>操作系统</b>解读