20135327郭皓——信息安全系统设计基础第十一周学习总结

第十一周(11.16-11.22):

 

学习计时:共6小时linux

读书:程序员

代码:数组

做业:数据结构

博客:并发

1、学习目标异步

1. 了解异常及其种类
2. 理解进程和并发的概念
3. 掌握进程建立和控制的系统调用及函数使用:fork,exec,wait,waitpid,exit,getpid,getppid,sleep,pause,setenv,unsetenv,
4.  理解数组指针、指针数组、函数指针、指针函数的区别
5. 理解信号机制:kill,alarm,signal,sigaction
6. 掌握管道和I/O重定向:pipe, dup, dup2
 
 
 
 

第八章 异常控制流

  • 现代系统经过使控制流发生突变来对这些状况作出反应。咱们把这些突变称为异常控制流ide

  • 做为程序员,理解 ECF 很重要:函数

    • 理解 ECF 将帮助你理解重要的系统概念。
    • 理解 ECF将帮助你理解应用程序是如何与操做系统交互的。
    • 理解 ECF 将帮助你编写有趣的新应用程序。
    • 理解 ECF 将帮助你理解并开发。
    • 理解 ECF 将帮助你理解软件异常如何工做。
 

8.1 异常

  • 异常是异常控制流的一种形式,它一部分是由硬件实现的,一部分是由操做系统实现的
  • 异常( exception)就是控制流中的突变,用来响应处理器状态中的某些变化。
  • 当异常处理程序完成处理后,根据引发异常的事件的类型,会发生如下三种状况中的一种: 
    1)处理程序将控制返回给当前指令 curr 即当事件发生时正在执行的指令。 
    2) 处理程序将控制返回给 酬,即若是没有发生异常将会执行的下一条指令。 
    3) 处理程序终止被中断的程序。
 

8.1.1 异常处理

  • 系统中可能的每种类型的异常都分配了一个惟一的非负整数的异常号。
  • 异常表的起始地址放在一个叫作异常在基址寄存器的特殊CPU 寄存器里。
  • 异常相似于过程调用,可是有一些重要的不 
    同之处。 
    • ·过程调用时,在跳转处处理程序以前,处理器将返回地址压人找中。
    • 处理器也把一些额外的处理器状态压到栈里,在处理程序返回时,从新开始被中断的程序会须要这些状态。
    • 若是控制从一个用户程序转移到内核,那么全部这些项目都被压到内核栈中,而不是压到用户栈中。
    • 异常处理程序运行在内核模式下,这意味着它们对全部的系统资源都有彻底的访问权限。
 

8.1.2 异常的类别

  • 异常能够分为四类:中断( interrupt)、陷阱 (trap)、故障 (fault) 和终止 (abort)。

1.中断工具

  • 中断是异步发生的,是来自处理器外部的1/ 设备的信号的结果。
  • 硬件中断的异常处理程序一般称为中断处理 
    程序。
  • 剩下的异常类型(陷阱、故障和终止〉是同步发生的,是执行当前指令的结果。咱们把这类指令叫作故障指令。

2.陷阱和系统调用学习

  • 陷阱是有意的异常,是执行一条指令的结果。就像中断处理程序同样,陷阱处理程序将控制返回到下一条指令。陷阱最重要的用途是在用户程序和内核之间提供一个像过程同样的接口,叫作系统调用。

3.故障

  • 故障由错误状况引发,它可能可以被故障处理程序修正。当故障发生时,处理器将控制转移给故障处理程序。若是处理程序可以修正这个错误状况,它就将控制返回到引发故障的指令,从而从新执行它。不然,处理程序返回到内核中的 abort 例程, abort 例程会终止引发故障的应用程序。

4.终止

  • 终止是不可恢复的致命错误形成的结果,一般是一些硬件错误,好比 DRAM 或者SRAM被损坏时发生的奇偶错误。终止处理程序从不将控制返回给应用程序。
 

8.1.3 Linux/IA32系统中的异常

  1. Linux/IA32故障和终止
  • 除法错误
  • 通常保护故障
  • 缺页
  • 机器检查

2.linuxllA32 系统调用

  • Linux 提供上百种系统调用,当应用程序想要请求内核服务时可使用,包括读文件、写文件或是建立一个新进程。

 

8.2 进程

  • 异常是容许操做系统提供进程 (process) 的概念所须要的基本构造块,进程是计算机科学中 
    最深入最成功的概念之一。
  • 进程提供给应用程序的关键抽象: 
    • 一个独立的逻辑控制流,它提供一个假象,好像咱们的程序独占地使用处理器。
    • 一个私有的地址空间,它提供一个假象,好像咱们的程序独占地使用存储器系统。
 

8.2.1 逻辑控制流

  • 若是想用调试器单步执行程序,咱们会看到一系列的程序计数器 (PC)值,这些值惟一地对应于包含在程序的可执行目标文件中的指令,或者是包含在运行时动态连接到程序的共享对象中的指令。这个 PC值的序列叫作这辑控制流,或者简称逻辑流。
  • 每一个进程执行它的流的一部分,而后被抢占 (preempted) (暂时挂起),而后轮到其余进程。
 

8.2.2 并发流

  • 一个逻辑流的执行在时间上与另外一个流重叠,称为并发流 (concurrent fiow) ,这两个流被称为并发地运行.
  • 多个流并发地执行的通常现象称为并发 (concurrency)。一个进程和其余进程轮流运行的 
    概念称为多任务 (multitang).一个进程执行它的控制流的一部分的每一时间段叫作时间片(time slice)。所以,多任务也叫作时间分片(time.slicing).
 

8.2.3 私有地址空间

  • 进程也为每一个程序提供一种假象,好像它独占地使用系统地址空间。在一台有 位地址的机器上,地祉空间是 个可能地址的集合 0, 1,…, -l. 一个进程为每一个程序提供它本身的私有地址空间。
 

8.2.4 用户模式和内核模式

  • 处理器一般是用某个控制寄存器中的一个模式位 (mode bω 来提供这种功能的,该寄存器描述了进程当前享有的特权。当设置了模式位时,进程就运行在内核模式中(有时叫作超级用户模式)。一个运行在内核模式的进程能够执行指令集中的任何指令,而且能够访问系统中任何存储器位置。
  • 没有设置模式位时,进程就运行在用户模式中。用户模式中的进程不容许执行特权指令(privi1eged instruction),好比中止处理器、改变模式位,或者发起一个I/O操做。也不容许用户模式中的进程直接引用地址空间中内核区内的代码和数据。任何这样的尝试都会致使致命的保护故障。反之,用户程序必须经过系统调用接口间接地访问内核代码和数据。
 

8.2.5 上下文切换

  • 操做系统内核使用一种称为上下丈切换 (context switch) 的较高层形式的异常控制流来实现多任务。
  • 内核为每一个进程维持一个上下文(context)。上下文就是内核从新启动一个被抢占的进程所需的状态。
  • 在进程执行的某些时刻,内核能够决定抢占当前进程,并从新开始一个先前被抢占的进程。这种决定就叫作调度,是由内核中称为调度器( scheduler)的代码处理的。
  • 当内核选择一个新的进程运行时,咱们就说内核调皮了这个进程。在内核调度了一个新的进程运行后,它就抢占当前进程,并使用一种称为土下丈切换的机制来将控制转移到新的进程,上下文切换 
    1)保存当前进程的上下文, 
    2) 恢复某个先前被抢占的进程被保存的上下文, 
    3) 将控制传递给这个新恢复的进程。

 

8.3 系统调用错误处理

见书P491

 

8.4 进程控制

 

8.4.1 获取进程ID

  • 每一个进程都有一个惟一的正数(非零)进程 ID (PID). getpid 函数返回调用进程的 PID。getppid 画数返回它的父进程的 PID (建立调用进程的进程〉。
  • getpid getppid 函数返回一个类型为 pid_t 的整数值,在 Linux 系统上它在 types.h中被定义为 int。
 

8.4.2 建立和终止进程

  • 进程老是处于下面三种状态之-:

    • 运行。进程要么在CPU上执行,要么在等待被执行且最终会被内核调度。
    • 中止。进程的执行被挂起(suspend),且不会被调度。当收到 SIGSTOP、SIGTSTP、SIDTTN或者 SIGTTOU 信号时,进程就中止,而且保持中止直到它收到一个 SIGCONT 
      信号,在这个时刻,进程再次开始运行。
    • 终止。进程永远地中止了。进程会由于三种缘由终止: 
      1) 收到一个信号,该信号的默认行为是终止进程。 
      2) 从主程序返回。 
      3) 调用 exit 函数。
  • fork函数的特色

    • 调用一次,返回两次
    • 并发执行
    • 相同可是独立的地址空间
    • 共享文件

8.4.3 回收子进程

  • 当一个进程因为某种缘由终止时,内核并非当即把它从系统中清除。相反,进程被保持在一种己终止的状态中,直到被它的父进程回收 (reap)。当父进程回收已终止的子进程时,内核 
    将子进程的退出状态传递给父进程,而后抛弃已终止的进程,今后时开始,该进程就不存在了。一个终止了但还未被回收的进程称为僵死进程 (zombie)。
  • waitpid函数 
    1. 判断等待集合的成员 
      等待集合的成员是由参数 pid 来肯定的: 
      • 若是 pid>0,那么等待集合就是一个单独的子进程,它的进程lD等于 pid
      • 若是 pid = -1 ,那么等待集合就是由父进程全部的子进程组成的。
    2. 修改默认行为 
      能够经过将 optioins 设置为常量 WNOHANG WUNTRAα 的各类组合,修改默认行为: 
      • WNOHANG: 若是等待集合中的任何子进程都尚未终止,那么就当即返回(返回值为0)。默认的行为是挂起调用进程,直到有子进程终止。在等待子进程终止的同时,若是还想作些有用的工做,这个选项会有用。
      • WUNTRACED :挂起调用进程的执行,直到等待集合中的一个进程变成已终止或者被中止。返回的 PID 为致使返回的己终止或被中止子进程的 PID。默认的行为是只返回己终止的子进程。当你想要检查已终止和被中止的子进程时,这个选项会有用。
      • WNOHANG UNTRACED: 当即返回,若是等待集合中没有任何子进程被中止或已终止,那么返回值为 ,或者返回值等于那个被中止或者己终止的子进程的 PID
    3. 检查已回收子进程的退出状态 
      若是 status 参数是非空的,那么 waitpid 就会在 status 参数中放上关于致使返回的子进程的状态信息。 wait.h 头文件定义了解释 status 参数的几个宏 
      • WIFEXITED (status) :若是子进程经过调用 exit 或者一个返回 (return) 正常终止,就返回真。
      • WEXITSTATUS (status) 返回一个正常终止的子进程的退出状态。只有在 WIFEXITED返回为真时,才会定义这个状态。
      • WIFSIGNALED (status): 若是子进程是由于一个未被捕获的信号终止的,那么就返回真。
      • WTERMSIG (status): 返回致使子进程终止的信号的数量。只有在 WIFSIGNALED(status) 返回为真时,才定义这个状态。
      • WIFSTOPPED (status) :若是引发返回的子进程当前是被中止的,那么就返回真。
      • WSTOPSIG (status): 返回引发子进程中止的信号的数量。只有在 WIFSTOPPED(status) 返回为真时,才定义这个状态。
    4. 错误条件 
      • 若是调用进程没有子进程,那么waitpid返回-1,而且设置 errno为ECHILD。若是waitpid函数被一个信号中断,那么它返回一1,并设置 errno为EINTR
    5. wait函数 
      • wait函数是waitpid函数的简单版本。
      • 调用 wait(&status) 等价于调用 waitpid(-l &status , 0)
 

8.4.4 让进程休眠

  • sleep函数将一个进程挂起一段指定的时间。
 

8.4.5 加载并运行程序

  • exceve函数在当前进程的上下文中加载并运行一个新程序
  • execve 函数加载并运行可执行目标文件filename,且带参数列表 argv和环境变量列表envp。

 

8.5 信号

  • 一个信号就是一条小消息,它通知进程系统中发生了一个某种类型的事件。
 

8.5.1 信号术语

  • 传送一个信号到目的进程是由两个不一样步骤组成的: 
    • 发送信号。内核经过更新目的进程上下文中的某个状态,发送(递送)一个信号给目的进程。发送信号能够有以下两个缘由: 
      1)内核检测到一个系统事件,好比被零除错误或者 
      子进程终止。 
      2) 一个进程调用了kill函数,显式地要求内核发送一个信号给目的进程。一个进程能够发送信号给它本身。
    • 接收信号。当目的进程被内核强迫以某种方式对信号的发送作出反应时,目的进程就接收了信号。进程能够忽略这个信号,终止或者经过执行一个称为信 处理程的用户层函数捕获这个信号。
  • 一个只发出而没有被接收的信号叫作待处理信号。
 

8.5.2 发送信号

  1. 进程组 
    • Unix 系统提供了大量向进程发送信号的机制。全部这些机制都是基于进程组这个概念的。
    • 每一个进程都只属于一个进程组,进程组是由一个正整数进程纽 ID来标识的。getpgrp函数返回当前进程的进程组 ID:
    • 默认地,一个子进程和它的父进程同属于一个进程组。一个进程能够经过使用setpgid数来改变本身或者其余进程的进程组:

  2. 用/bin/kill 程序发送信号 

    • /bin/kill 程序能够向另外的进程发送任意的信号。好比,命令 

ix> /bin/ki11 -9 15213

  3. 从键盘发送信号 

    • Unix 外壳使用做业这个抽象概念来表示为对一个命令行求值而建立的进程。在任什么时候刻,至多只有一个前台做业和个或多个后台做业。

  4. 用kill函数发送信号 

    • 进程经过调用kill函数发送信号给其余进程(包括它们本身)。若是pid大于霉,那么kill函数发送信号 sig 给进程 pid。若是pid小于霉,那么kill 发送信号 sig 给进程组 abs (pid) 中的每一个进程。

  5. 用alarm函数发送信号 

    • 进程能够经过调用alarm函数向它本身发送SIGALRM信号。

 

8.5.3 接收信号

  • 当内核从一个异常处理程序返回,准备将控制传递给进程 时,它会检查进程的未被阻塞的待处理信号的集合。若是这个集合为空(一般状况下),那么内核将控制传递到的逻辑控制流中的下一条指令。
  • 然而,若是集合是非空的,那么内核选择集合中的某个信号而且强制接收信号k.收到这个信号会触发进程的某种行为。一旦进程完成了这个行为,那么控制就传递回的逻辑控制流中的下一条指令(]next)。每一个信号类型都有一个预约义的默认行为,是下面中的一种 
    • 进程终止。
    • 进程终止并转储存储器 (dump core)
    • 进程中止直到被 SIGCONT 信号重启.
    • 进程忽略该信号。

  • signal 函数能够经过下列三种方法之一来改变和信号signum相关联的行为 
    • 若是 handler是SIG_IGN,那么忽略类型为signum的信号。
    • 若是 handler是SIG_DFL,那么类型为signum的信号行为恢复为默认行为。
    • 不然, handler就是用户定义的函数的地址,这个函数称为信号处理程序,只要进程接收到一个类型为 signum的信号,就会调用这个程序。经过把处理程序的地址传递到signal函数从而改变默认行为,这叫作设置信号处理程序。调用信号处理程序称为捕获信号。执行信号处理程序称为处理信号。
 

8.5.4 信号处理问题

  • 对于只捕获一个信号并终止的程序来讲,信号处理是简单直接的。然而,当一个程序要捕获多个信号时,一些席位问题就出现了: 
    • 待处理信号被阻塞
    • 待处理信号不会排队等待
    • 系统调用能够被中断
  • 重要教训:不能够用信号来对其它进程中发生的事件计数。
 

8.5.5 可移植的信号处理

  • 不一样系统之间,信号处理语义的差别〈好比一个被中断的慢速系统调用是重启仍是永久放弃)Unix信号理的一个缺陷。为了处理这个问题, Posix标准定义了 sigaction 函数,它容许像Linux和Solaris这样与Posix 兼容的系统上的用户,明确地指定他们想要的信号处理语义。
  • Signal 包装函数设置了一个信号处理程序,其信号处理语义以下: 
    • 只有这个处理程序当前正在处理的那种类型的信号被阻塞。
    • 和全部信号实现同样,信号不会排队等待。
    • 只要可能,被中断的系统调用会自动重启。
    • 一旦设置了信号处理程序,它就会一直保持,直到 Signal带着handler参数为SIG_IGN或者SIG_DFL被调用。
 

8.5.6 显式地阻塞和取消阻塞信号

  • 应用程序可使用sigprocmask函数显式地阻塞和取消阻塞选择的信号:
  • sigprocmask 函数改变当前已阻塞信号的集合。具 
    体的行为依赖于 how 的值: 
    • SIG_BLOCK: 添加 set 中的信号到 blocked (blocked = blocked | set).
    • SIG_UNBLOCK: blocked 中删除 set 中的信号 (blocked = blocked & ~set)
    • SIG_SETMASK: blocked = set
 

8.5.7 同步流以免讨厌的并发错误

 

8.6 非本地跳转

  • C语言提供了一种用户级异常控制流形式,称为非本地跳转,它将控制直接从一个函数转移到另外一个当前正在执行的函数,而不须要通过正常的调用-返回序列。非本地跳转是经过setjmp和longjmp函数来提供的。
 

8.7 操做进程的工具

  • Linux 系统提供了大量的监控和操做进程的有用工具:
    • STRACE:打印一个正在运行的程序和它的子进程调用的每一个系统调用的轨迹。
    • PS: 列出当前系统中的进程(包括僵死进程)。
    • TOP: 打印出关于当前进程资源使用的信息。
    • PMAP: 显示进程的存储器映射。
    • /proc: 一个虚拟文件系统,以ASCII文本格式输出大量内核数据结构的内容,用户程序可读取这些内容。
 

小结

  • 异常控制流(ECF)发生在计算机系统的各个层次,是计算机系统中提供并发的基本机制。 
    • 在硬件层,异常是由处理器中的事件触发的控制流中的突变。控制流传递给一个软件处理程序,该处理程序进行一些处理,而后返回控制给被中断的控制流。
    • 有四种不一样类型的异常中断、故障、终止和陆阱。当一个外部I/O设备,例如定时器芯片或者一个磁盘控制器,设置了处理器芯片上的中断引脚时,中断会异步地发生。
    • 控制返回到故障指令后面的那条指令。一条指令的执行可能致使故障和终止同时发生。故障处理程序会从新启动故障指令,而终止处理程序从不将控制返回给被中断的流。最后,陆阱就像是用来实现向应用提供到操做系统代码的受控的人口点的系统调用的函数调用。 
    • 主要来讲这一章要重点理解掌握代码,理解知识点。
相关文章
相关标签/搜索