zoukankan      html  css  js  c++  java
  • 中断与系统调用

    中断机制

    中断及其分类

      中断是指程序执行过程中,遇到紧急处理的事件时,暂停中止CPU上现行程序的运行,转去执行相应的事件处理程序,待处理完成后再返回原程序被中断处或调度其他程序执行的过程。

      中断分为:硬中断和软中断。

      硬中断分成外中断和内中断。外中断又称为中断或异步中断,是指来自CPU以外的中断信号,外中断还分屏蔽中断和不可屏蔽中断,不同中断有不同的中断优先级,表示事件的紧急程度。内中断又称异常或同步中断,是指来自CPU内部,在程序执行过程中,发现的与当前指令关联的,不正常的错误的事件,linux 异常可被细分为4种:故障,陷阱,终止和编程异常。编程异常用来实现系统调用,进程自愿进入内核态义请求系统服务。

      中断和异常要通过硬件设施来产生中断请求,这些都是硬中断,与其相对应的不必由硬件产生中断源而能引发的一种中断称为软中断。软中断分为:信号和软件中断。

      操作系统中,除一部分低层硬件异常由内核异常处理程序处理外,大部分异常均转化为信号再进行处理,由于异常与当前运行进程紧密相关,每当执行指令产生异常事件,可通过信号处理程序向当前运行进程发出一个信号。

    系统调用的概念

      程序员或系统管理员通常并非直接和系统调用打交道,在实际应用中,程序员调用的的函数,或称为应用程序接口(API),管理员使用的则是更高层次的系统命令。操作系统为每个系统调用在标准C函数库中构造一个具有相同名字的封装函数,由它来屏蔽下层的复杂性,负责把操作系统提供的服务接口----系统调用-----封装成应用程序能够直接调用的函数(库函数)

      系统调用通过中断机制向内核提交请求,它的功能由内核函数实现,进入内核后不同系统调用找到各自对应的内核函数,这些内核函数就是系统调用的“服务例程”。API实质上是一个函数定义,说明如何获得一个给定服务,如read(),malloc(),free()等。它有可能和系统调用形式上一致,如read()函数就和read()系统调用对应,但未必总是一一对应,往往会出现不同函数的内部用到同一个内核函数,如malloc(),free()内部均利用sys_brk()内核函数来扩大或缩小进程堆;一个函数也可利用几个内核函数组合完成任务,有些函数不需要任何内核函数,它的实现与内核无关。系统命令相对与编程接口有更高的层次,它们是内部引用函数的可执行程序,如常用的系统命令ls,hostname等,而这些命令的实现大多数依靠系统调用。

      下面以read()为例来了解系统调用的执行流程,当应用程序调用read(fd,buffer,nbytes)函数时,该函数在Linux/GNU提供的标准C库,即libc中,对应的封装函数由下面汇编指令实现:

          movel  $3,%eax

          movel  fd,%ebx

          movel  buffer,%ecx

          movel  nbutes,%edx      

          int  $0x80

      在Linux中规定int  $0x80指令是系统调用的总入口,若干个寄存器中存放应用程序传递个内核的参数。内核为了区分不同的系统调用,需要给每个都分配唯一的系统调用号,而相对应的内核函数的入口地址都放在系统调用表中。内核在获得系统调用号后根据寄存器EAX中调用号的值跳转到系统调用表相应的内核函数,以完成应用程序请求的服务。

    系统调用的执行流程

      系统调用与普通C语言函数调用最大的区别在于系统调用需要陷入内核态,发生特权级的转换。

      1.保存现场  2.跳到内核函数  3.参数传递  

      4.系统调用封装

      应用程序发出的系统调用是同步事件,虽然它在内核态执行,但却在调用进程的上下文中,所以既可以访问进程地址空间,也可以访问内核空间。system_call()在内核栈上保存硬件上下文,然后使用系统调用号作为系统调用表system_call_table的索引,以确定system_call()应该执行哪个系统调用对应的内核函数。当系统调用执行结束后,system_call()在对应的寄存器EAX中放入返回的int值或错误码,并从内核栈恢复硬件上下文,回到用户态并把控制权交给库函数,库函数再返回给应用程序。

      5.系统调用上下文

      内核在执行系统调用时处于进程上下文中,current指针指向当前进程,即引发系统调用的进程。在进程上下文中,内核可以阻塞或被抢占。首先,能够阻塞说明系统调用可以使用内核提供的绝大部分功能,从而给内核编程带来方便;其次,再进成上下文中能够被抢占,其实表明像用户空间内的进程一样,当前进程同样可以被其他进程抢占,当然因为新进程可以使用相同的系统调用,所以必须保证该系统调用是可重人的。当系统调用返回时,控制权仍然在system_call()中,它最终会负责切换到用户空间并让应用程序继续进行。

  • 相关阅读:
    JS中iframe子页面与父页面之间通信
    .NET 大数据量并发解决方案
    angular的性能分析 -随记
    第二次作业
    自我介绍
    总结作业
    2019春第四次课程设计实验报告
    2019春第三次课程设计实验报告
    2019春第二次课程设计实验报告
    第十二周作业
  • 原文地址:https://www.cnblogs.com/qiaoshanzi/p/3082550.html
Copyright © 2011-2022 走看看