2018-2019-1 20165329 《信息安全系统设计基础》第七周学习总结
2018-2019-1 20165329 《信息安全系统设计基础》第七周学习总结
教材内容总结:
8.1异常
-
异常处理程序运行在内核模式下,它们对所以的系统资源都有完全的访问权限。
- 异常是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现。异常是控制流中的突变,用来响应处理器状态中的某些变化。
-
异常的种类:异常可分为四类,中断、陷阱、故障和终止。
-
陷阱是有意的异常,是执行一条指令的结果。
- 中断是异步产生的,是来自处理器外部的I/O设备的信号的结果。
-
故障由错误情况引起,它可能能够被故障处理程序修正。
-
终止是不可恢复的致命错误造成的结果,通常是一些硬件错误。
- Linux/IA32故障和终止除法错误;一般保护故障;缺页;机器检查
- Linux/IA32系统调用:每个系统调用都有一个唯一的整数号,对应于一个到内核中跳转表的偏移量。
- 寄存器%rax包含系统调用号
- 从系统调用返回时,寄存器%rcx和%rll都会被破坏,%rax包含返回值
如下图所示:
8.2 进程
- 进程就是一个执行中的程序实例。系统中的每个程序都是运行在某个进程的上下文中的。
- 进程提供给应用程序的关键抽象:一个独立的逻辑控制流 ;一个私有的地址空间。
- 程序计数器(PC)值的序列叫做逻辑控制流,简称逻辑流。
- 并发流:并发流一个逻辑流的执行在时间上与另一个流重叠,叫做并行流
- 并发:多个流并发执行的一般现象称为并发。
- 多任务:多个进程并发叫做多任务。
- 并行:并发流在不同的cpu或计算机上,叫做并行。
- 地址空间底部是保留给用户程序的,包括通常的代码、数据、堆和栈段。
- 代码段总是从地址0x400000开始。
- 调度:内核中的调度器实现调度。
- 上下文切换:保存当前进程的上下文;恢复某个先前被抢占的进程被保存的上下文;将控制传递给这个新恢复的进程
- 当内核代表用户执行上下文切换时,可能会发生上下文切换。如果系统调用发生阻塞,那么内核可以让当前进程休眠,切换到另一个进程。
8.4 进程控制
- getpid函数返回调用进程的PID。
- getppid函数返回它的父进程的PID
- 进程的三种状态——运行、停止和终止。
- 进程会因为三种原因终止进程:(1)收到信号,该信号默认终止进程;(2)从主程序返回;(3)调用exit函数。
- fork函数:(1)调用一次,返回两次;(2)并发执行;(3)相同但是独立的地址空间;(4)共享文件
- 回收:当一个进程终止时,内核并不立即把它从系统中清除。相反,进程被保持在一种已终止的状态中,直到被它的父进程回收。
- 僵死进程:一个终止了但是还未被回收的进程称为僵死进程。
- 回收子进程的两种方法:内核的init进程;父进程waitpid函数
- waitpid函数有点复杂,默认地(当options=0时),waitpid挂起调用进程的执行,知道它的等待集合中的一个子进程终止。
- sleep函数将一个进程挂起一段指定的时间。
- 如果请求的时间量已经到了,sleep返回0,否则返回还剩下的要休眠的秒数。后一种情况是可能的,如果因为sleep函数被一个信号中断而过早地返回。
- pause函数让调用函数休眠,直到该进程收到一个信号。
- execve函数加载并运行可执行目标文件filename,且带参数列表argv和环境变量列表envp。与fork一次调用返回两次不同,execve调用一次并从不返回。
- 参数中每个指针都指向一个参数串。
8.5 信号
- 一种更高层次的软件形式的异常,称为unix信号,它允许进程中断其他进程。
- 低层的硬件异常是由内核异常处理程序处理的,正常情况下,对用户进程而言是不可见的。信号提供了一种机制,通知用户进程发生了这些异常。
- 传送一个信号到目的进程是由两个步骤组成的发送信号。内核通过更新目的进程上下文中的某个状态,发送(递送)一个信号给目的进程。发送信号可以有如下两种原因:
- (1)内核检测到一个系统事件。
- (2)一个进程调用了kill函数,显式地要求内核发送一个信号给目的进程,一个进程可以发送信号给它自己。
- 接收信号:当目的进程被内核强迫以某种方式的发送做出反应时,目的进程就接收了信号。进程可以忽略这个信号,终止或者通过执行一个称为信号处理程序的用户层函数不活这个信号。
- 一个只发出而没有被接收的信号叫做待处理信号。在任何时刻,一种类型至多只会有一个待处理信号。
- 一个进程可以有选择性地阻塞接收某种信号。当一种信号被阻塞时,他仍可以被发送,但是产生的待处理信号不会被接收,直到进程取消对这种信号的阻塞。一个待处理信号最多只能被接收一次。
- 进程组:每个进程都只属于一个进程组,进程组是由一个正整数进程组ID来标识的。 一个子进程和它的父进程同属于一个进程组,一个进程组可以通过使用setpgid函数来改变自己或者其他进程的进程组。
- 用/bin/kill程序发送信号,用/bin/kill程序可以向另外的进程发送任意的信号。
- 从键盘发送信号,从键盘发送信号外壳为每个作业创建一个独立的进程组。
- 用kill函数发送信号进程通过调用kill函数发送信号给其他进程(包括它们自己)。
- 用alarm函数发送信号进程可以通过调用alarm函数向他自己发送SIGALRM信号。
- 当内核从一个异常处理程序返回,准备将控制传递给进程P时,他会检查进程P的未被阻塞的处理信号的集合。如果这个集合为空,那么内核将控制传递到P的逻辑控制流中的下一条指令;如果集合是非空的,那么内核选择集合中的某个信号K(通常是最小的K0,并且强制P接收信号K。收到这个信号会触发进程的某种行为。一旦进程完成了这个行为,那么控制就传递回P的逻辑控制流中的下一条指令。
- 每个信号类型都有一个预定的默认行为:
- (1)进程终止
- (2)进程终止并转储存储器
- (3)进程停止直到被SIGCONT型号重启
- (4)进程忽略该信号
- signal函数可以通过下列三种方法之一来改变和信号signum相关联的行为:
- (1)如果handler是SIG_IGN,那么忽略类型为signum的信号
- (2)如果handler是SIG_DFL,那么类型为signum的信号行为恢复为默认行为
- (3)否则,handler就是用户定义的函数的地址,这个函数成为信号处理程序,只要进程接收到一个类型为signum的信号,就会调用这个程序,通过把处理程序的地址传递到signal函数从而改变默认行为,这叫做设置信号处理程序。
- 当一个程序要捕获多个信号时,一些细微的问题就产生了。
- (1)待处理信号被阻塞。Unix信号处理程序通常会阻塞当前处理程序正在处理的类型的待处理信号。
- (2)待处理信号不会排队等待。任意类型至多只有一个待处理信号。因此,如果有两个类型为K的信号传送到一个目的进程,而由于目的进程当前正在执行信号K的处理程序,所以信号K时阻塞的,那么第二和信号就简单地被简单的丢弃,他不会排队等待。
- (3)系统调用可以被中断。像read、wait和accept这样的系统调用潜在地会阻塞进程一段较长的时间,称为慢速系统调用。在某些系统中,当处理程序捕获到一个信号时,被中断的慢速系统调用在信号处理程序返回时不再继续,而是立即返回给用户一个错误的条件,并将errno设置为EINTR。
- Signal包装函数设置的信号处理程序的信号处理语义:
- (1)只有这个处理程序当前正在处理的那种类型的信号被阻塞
- (2)和所有信号实现一样,信号不会排队等候
- (3)只要有可能,被中断的系统调用会自动重启。
- (4)一旦设置了信号处理程序,它就会一直保持,知道signal带着handler参数为SIG_IGN或者SIG_DFL被调用。
8.6 非本地跳转
- c语言提供了一种用户级异常控制流形式,称为本地跳转。通过setjmp和longjmp函数来提供。
- setjmp函数只被调用一次,但返回多次:一次是当第一次调用setjmp,而调用环境保存在缓冲区env中时,一次是为每个相应的longjmp调用。另一方面,longjmp只调用一次,但从不返回。sig—函数是setjmp和longjmp函数的可以被信号处理程序使用的版本。
- 非本地跳转的一个重要应用就是允许从一个深层嵌套的函数调用中立即返回,通常是由检测到某个错误情况引起的。
- 非本地跳转的另一个重要应用是使一个信号处理程序分支到一个特殊的代码位置,而不是返回到达中断了的指令位置。