0

0

系统调用的目的是什么

晓曦&sea

晓曦&sea

发布时间:2020-07-16 17:44:17

|

11827人浏览过

|

来源于php中文网

原创

系统调用的目的是:请求系统服务。操作系统不允许用户直接操作各种硬件资源,因此用户程序只能通过系统调用的方式来请求内核为其服务,间接地使用各种资源。

系统调用的目的是什么

由操作系统提供的功能,通常应用程序本身是无法实现的。例如对文件进行操作,应用程序必需通过系统调用才能做到,因为只有操作系统才具有直接管理外围设备的权限。又如进程或线程间的同步互斥操作,也必需经由操作系统对内核变量进行维护才能完成。

从下到上看一个完整的计算机系统:物理硬件->OS内核->OS服务->应用程序。这里的OS内核起到了“承上启下”的关键作用,向下管理物理硬件,向上为操作系统服务和应用程序提供接口,这里的接口就是系统调用了。

应用程序的进程通常在user模式下运行,当它调用一个系统调用时,进程进入kernel模式,执行的是kernel内部的代码,从而具有执行特权指令的权限,完成特定的功能。换句话说,系统调用是应用程序主动进入操作系统内核的入口。

一、系统调用和库函数的区别

库函数

顾名思义是把函数放到库里,是把一些常用到的函数编完放到一个文件里,供别人用。别人用的时候把所在的文件名用#include加到里面就可以了,一般放到lib文件里。

库函数主要由两方面提供:一是操作系统提供的;另一类是由第三方提供的。

  • 系统提供的这些函数把系统调用进行封装或者组合,可以实现更多的功能,这样的库函数能够实现一些对于内核来说比较复杂的操作。比如read函数根据参数,直接就能读文件,而背后隐藏的文件比如在那个磁道,那个扇区,加载到那个内存,是程序员不必关心的问题。这些操作里面也包含了系统调用。比如write()这个系统函数,会调用同名的系统调用,来完成写入操作。

  • 对于第三方库,其实和系统库一样,只是他直接利用系统调用的可能性要小一些,而是系统提供的API接口来是实现。比如printf,实际上调用了write()这个系统函数。 第三方库函数大部分是对系统函数的封装。

系统调用和库函数的联系:

事实上,系统调用所提供给用户的是直接而纯碎的高级服务,如果想要更加人性化,具有更符合特定情况的功能,那么就要我们用户自己定义,因此衍生了库函数,它把部分系统调用包装起来。比如当我们要用C语言打印一句话的时候,如果没有用到库函数printf,那么我们就需要自己实现就需要调用putc()和write()等这样一些系统函数。显得比较麻烦,所以系统调用是为了方便使用操作系统的接口,而库函数则是为了人们编程的方便。

例如,在Linux操作系统下,C语言的库函数printf,实际上使用了write系统调用;而库函数strcpy(字符串拷贝)却没有使用任何系统调用。另外,一个系统的系统调用接口通常是能够完成所有必需功能的最小集合,可能存在多个库函数对同一个系统调用进行封装。例如,在Linux中,malloc、calloc和free三个库函数底层都是调用brk系统调用完成的。

应用程序、库函数和系统调用的关系如下图所示:

1.gif

系统调用和库函数的区别:

库函数的调用是语言或者应用程序的一部分,而系统调用则是操作系统的一部分。

系统调用是应用程序与内核交互的接口。人们在长期的编程中发现使用系统函数有个重大的缺点,那就是程序的移植性。例如linux提供的系统调用的函数和windows就不一样。

库函数调用则是面向应用开发的,相当于应用程序的api,采用这样的方式有很多原因:

  • 双缓冲技术;(库函数和系统调用两层缓冲,减少系统调用次数)
  • 移植性(封装了不同操作系统的系统函数,对外接口一致)
  • 底层调用本身存在的一些缺陷;
  • 让api也可以有了级别和专门的工作面向;

二、CPU的内核模式和用户模式

通常,处理器设有两种模式:“用户模式”与“内核模式”,通过一个标签位来鉴别当前正处于什么模式。内核模式可以运行所有指令,包括特权指令(主要是一些硬件管理的指令,例如修改基址寄存器内容的指令) ,而用户模式不能执行特权指令。这样的设计主要为了安全问题,即由操作系统负责管理硬件,避免上层应用因错误设计而导致硬件问题。

既然只有操作系统能直接操作硬件,操作系统有必要提供接口来为应用程序提供使用硬件功能的入口,这些接口就被称为系统调用。

当操作系统接收到系统调用请求后,会让处理器进入内核模式,从而执行诸如I/O操作,修改基址寄存器内容等指令,而当处理完系统调用内容后,操作系统会让处理器返回用户模式,来执行用户代码。

对应CPU的内核模式和用户模式,进程运行的状态分为管态(核心态)和目态(用户态)。具体请看文章:操作系统--用户态和核心态

magento(麦进斗)
magento(麦进斗)

Magento是一套专业开源的PHP电子商务系统。Magento设计得非常灵活,具有模块化架构体系和丰富的功能。易于与第三方应用系统无缝集成。Magento开源网店系统的特点主要分以下几大类,网站管理促销和工具国际化支持SEO搜索引擎优化结账方式运输快递支付方式客户服务用户帐户目录管理目录浏览产品展示分析和报表Magento 1.6 主要包含以下新特性:•持久性购物 - 为不同的

下载

四、系统调用和中断的联系

中断(Interrupt)通常是指在CPU内部或外部发生了某个待处理的事件,从而CPU必需改变当前指令的执行顺序去处理这类事件。在介绍中断和系统调用的关系之前,下面先把中断做一个分类。

中断可以大体分为两大类:

  • Asynchronous interrupts(外中断): 由CPU外部的其它硬件产生,说这类中断是异步的,意思是中断信号可以在任意时间发射,与CPU本身的时钟节拍没有关系。如时钟中断,硬盘读写服务请求中断等。

  • Synchronous interrupts(内中断/异常):在CPU内部产生,说这类中断是同步的,意思是中断信号的发射时间一定在当前指令执行结束之后。一般来自CPU的内部事件或程序执行中的事件,如非法操作码、地址越界、浮点溢出等。

Synchronous interrupts (异常)又分为以下若干类:

  • Processor-detected exceptions:处理器在执行指令时检测到的中断,如除零操作。

  • Faults:发生了某个异常条件,但异常条件被消除后,原来的程序流程可以继续执行而不受任何影响,如缺页异常。注意触发中断的指令会被重新执行。

  • Traps:由陷入指令引起的中断,通常用于程序调试。

  • Aborts:CPU内部有重要错误发生,例如硬件错误或系统表值出现错误。一旦这种中断发生,错误将不可恢复,只能将当前进程终止。

  • Programmed exceptions:也称为 software interrupts (软中断) ,由程序员的代码主动发起的中断,用来实现系统调用。如在Linux中,就是用int 0x80指令实现系统调用。

至此,我们发现了中断与系统调用的关系:系统调用是一种特殊的中断类型(软中断)

五、内核对于系统调用的处理

在x86的机器中,用一个8bit的数字(0~255)来区分各种中断,这个数字被称为中断向量(vector)。其中一个中断向量,即128 (0x80),专门被用于执行系统调用。

在Linux系统中,存有一个系统表,叫做Interrupt DescriptorTable,简称IDT。IDT表共有256项,存放了从中断向量到相应处理例程(interrupt or exceptionhandler)的映射关系。当某个中断发生时,CPU从IDT表中查找到相应的处理例程的地址来执行。

系统调用的处理例程在IDT表中占有一项。这一项是在trap_init函数中被初始化的,如下:set_system_gate(SYSCALL_VECTOR,&system_call);。如前所述,上面代码中的SYSCALL_VECTOR的值是128。

当系统调用发生时,通过中断机制,系统调用例程system_call被调用。它的执行过程大概分为4个步骤:

1、从寄存器中取出系统调用号和输入参数,然后将这些寄存器的值压入kernel栈中。根据系统调用号查找系统调用分派表(system call dispatch table),找到系统调用服务例程(一个内核函数)。

2、调用查到的系统调用服务例程。

3、将系统调用服务例程的返回值出栈,重新保存在寄存器中。

上面描述的系统调用例程system_call在kernel空间中执行。在执行前,系统调用号和输入参数已经存入了寄存器,这个存入过程由user空间的代码完成。实际上,如同第一节所讲,每个真正的系统调用基本上都有一个封装它的库函数,一般是在这个库函数中完成系统调用号和输入参数的保存动作。当系统调用例程system_call执行完毕后,返回值通过寄存器再传回user空间的库函数。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

387

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

611

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

351

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

256

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

597

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

523

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

639

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

599

2023.09.22

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

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

精品课程

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

共28课时 | 4.4万人学习

PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.2万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

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

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