系统调用有什么目的

发布时间:2020-07-20 09:14:36 作者:Leah
来源:亿速云 阅读:390

今天就跟大家聊聊有关系统调用有什么目的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

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

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

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

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

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

库函数

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

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

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

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

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

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

系统调用有什么目的

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

在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空间的库函数。

看完上述内容,你们对系统调用有什么目的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

推荐阅读:
  1. 实时操作系统有什么目的
  2. eclipse创建springboot项目的方式有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

系统调用

上一篇:将用户当前表空间中的表和索引迁移到另一个表空间

下一篇:API是何时?以什么姿态开启了它的时代?

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》