2017-2018-1 20155301 《信息安全系统设计基础》第14周学习总结
教材第八章内容学习内容总结
异常
- 异常是控制流中的突变,用来响应处理器状态中的某些变化。
- 控制流是指控制转移序列,就是从一条指令到下一条指令
- 异常控制流:现代操作系统通过使控制流发生突变来对系统状态做出反应,这些突变称为异常控制流,异常控制流,其实讲的是控制各种状态,状态变化了,肯定有一定的方法可以检测,检测之后,就对应的转移控制。其实就是设置了一些条件,如果条件触发了,就做一些事情。核心就是这样的。
异常处理
- 异常表:当处理器监测到有事件发生时,通过一张叫做异常表的跳转表,进行一个间接过程调用,到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序),而这里所谓的事件就是在处理器中,状态被编码为不同的位和信号,状态变化就是事件。
- 异常号:系统中可能的某种类型的异常都分配了一个唯一的非负整数的异常号。异常号是到异常表中的索引。
- 当异常处理程序完成处理后,根据引起异常的事件的类型,会发生以下三种情况的一种: 1)处理程序将控制返回给当前指令Icurr,即当事件发生时正在执行的指令。
2)处理程序将控制返回给Inext,即如果没有发生异常将会执行的下一条指令。
3)处理程序终止被中断的程序。
- 异常表基址寄存器:异常表的起始地址存放的位置。
- 异常与过程调用的不同之处 1)过程调用时,在跳转到处理器之前,处理器将返回地址压入栈中。然而,根据异常的类型,返回地址要么是当前指令,要么是下一条指令。
2)处理器把一些额外的处理器状态压入栈里,在处理程序返回时,重新开始被中断的程序会需要这些状态。
3)如果控制从一个用户程序转移到内核,那么所有这些项目都被压到内核栈中,而不是压到用户栈中。
4)异常处理程序运行在内核模式下,意味着它们对所有的系统资源都有完全的访问权限。
异常的类别
- 中断:异步发生,是来自处理器外部的I/O设备的信号的结果。
1)硬件异常中断处理程序通常称为中断处理程序。
2)异步异常是有处理器外部的I/O设备中的时间产生的,同步异常是执行一条指令的直接产物。
3)陷阱、故障、终止时同步发生的,是执行当前指令的结果,我们把这类指令叫做故障指令。
- 陷阱和系统调用,陷阱最重要的用途是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用
1)普通的函数运行在用户模式中,用户模式限制了函数可以执行的指令的类型,而且它们只能访问与调用函数相同的栈。系统调用运行在内核模式中,内核模式允许系统调用执行指令,并访问定义在内核中的栈。
2)陷阱是有意的异常,最重要的用途是在用户程序和内核之间提供一个向过程一样的接口。
3)为了允许内核服务的受控访问,使用“syscall n”指令,跳转到一个异常处理程序的陷阱,处理程序对参数解码并调用适当的内核程序。
- 故障,是由错误情况引起的故障
- 终止,不可恢复的致命错误造成的结果,通常是一些硬件错误。
1)终止处理程序从不将控制返回给应用程序。
2)终止处理程序将控制直接返回给abort例程,直接终止该应用程序。
进程
- 进程,就是一个执行中的程序的实例,系统中的每个程序都是定义在运行在某个进程的上下文中的。异常是允许操作系统提供进程的概念所需要的基的本构造块。
- 进程提供给应用程序的关键抽象:
1)一个独立的逻辑控制流,独占地使用处理器
2)一个私有的地址空间,独占地使用存储器系统
- 逻辑控制流,程序计数器(PC)的值唯一地对应于包含在程序可执行目标文件中的指令,或者是包含在运行时动态链接到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流
- 进程轮流使用处理器,每个进程执行流的一部分,然后被抢占(暂时挂起)。
- 并发流:一个逻辑流的执行在时间上与另一个流重叠。
1)并发:多个流并发地执行的一般现象。
2)多任务:一个进程和其他进程轮流运行的概念。
3)时间片:一个进程执行它的控制流的一部分的每一时间段。
4)多任务也叫时间分片。
- 私有地址空间,一个进程为每个程序提供他自己的私有地址空间,一般而言,和这个空间中某个地址相关联的存储器字节不能被其他程序读或写,地址空间底部是保留给用户程序的,顶部保留给保留给内核,用来存放内核在代表进程执行时的指令。
上下文切换
- 上下文切换操作系统内核使用叫上下文切换的异常控制流来实现多任务。
- 上下文切换机制: 1)保存当前进程的上下文
2)恢复某个先前被抢占的进程被保存的上下文
3)将控制传递给这个新恢复的进程
- 引起上下文切换的情况
1)当内核代表用户执行系统调用时
2)中断时
系统调用错误
- 系统调用错误:当UNIX系统级函数遇到错误时,它们典型地会返回-1,并设置全局整数变量errno来表示什么出错了。
进程控制
- 每个进程有一个唯一的非零正数进程ID(PID)。
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); 返回调用进程的PID
pid_t getppid(void); 返回父进程的PID(创建调用进程的进程)
- 创建和终止进程
从程序员的角度,我们可以认为进程总处于下面三种状态之一:
1)运行:进程要么在CPU上执行,要么在等待被执行且最终会被内核调度。
2)停止:程序的执行被挂起,,且不会被调度。
3)终止:进程用永远停止了。终止原因是收到一个信号,默认行为是终止进程、从主进程返回、调用exit函数。
- 父进程通过调用fork创建一个新的运行子进程:父进程与子进程有相同(但是独立的)地址空间
子进程和父进程的异同: 1)不同之处就是有不同的PID
2)相同之处就是用户级虚拟地址空间,包括:文本、数据和bss段、堆以及用户栈。任何打开文件描述符,子进程可以读写父进程中打开的任何文件。
- fork函数定义如下:
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
- fork函数的特点
1)调用一次,返回两次
2)并发执行
3)相同的但是独立的地址空间
4)共享文件
回收子进程
- 当一个进程由于某种原因终止,内核不会将他马上清除,而是将进程保持在已终止的状态中,直到被他的父进程回收。
- 当父进程回收已终止的子进程时,内核将子进程的退出状态传递给父进程,然后抛弃已终止的进程。一个终止了但还未被回收的进程称为僵死进程。
- 一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止。默认地,当option=0时,waitpid挂起调用进程的执行,直到它的等待集合中的一个子进程终止。
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);
//返回:若成功,返回子进程的PID;若WNOHANG,返回0;若其他错误,返回-1。
当options=0时,调用这个函数的进程挂起,也就是这个进程处于函数中什么也不做,等待着,等待什么呢,等待其子进程终止,如果终止了一个,那么函数就返回了,返回的,就是终止的子进程的pid,并且将这个子进程从系统中除去。
- 有哪些等待的子进程?
1)pid=-1,那么就是所有的子进程
2)pid>0,那么就是一个子进程,当前pid表示的那个子进程。
-修改默认行为
1)options=WNOHANG时,如果没有终止的子进程,那么函数立即返回,返回0。
2)options=WUNTRACED时,和options=0类似,但这里还检测停止的子进程。
3)options=0只检测终止的子进程。且,本options不会将子进程从系统中除去。
4)options=WNOHANG|WNUNTRACED时,立即返回,返回值要么是停止或者终止的pid,要么是0。
- 错误条件
1)如果调用进程没有子进程,那么waitpid返回-1,并设置errno为ECHILD
2)如果函数被一个信号中断,那么返回-1,并设置errno为EINTR。
- wait函数:调用wai等价于调用waitpid(-1.&status,0),wait函数是waitpid函数的简单版本
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
//返回:若成功,返回子进程的PID;若错误,返回-1。
让进程休眠
- sleep函数:将进程挂起一段指定的时间
#include <unistd.h>
unsigned int sleep(unsigned int secs);
//返回:还要休眠的秒数
- pause函数:让调用函数休眠,直到该进程收到一个信号
#include <unistd.h>
int pause(void);
//返回:总是-1
加载并运行程序
- execve函数:在当前进程的上下文中加载并运行一个新程序。
#include <unistd.h>
int execve(const char *filename, const char *argv[], const char *envp[]);
成功不返回,错误返回-1。 execve的参数相关说明:
1)filename:可执行目标文件
2)argv:带参数列表
3)envp:环境变量列表
execve函数调用一次,从不返回。
- getenv函数:在环境数组中搜素字符串“name =VALUE”,若找到了,就返回一个指向value的指针,否则它就返回NULL
#include <stdlib.h>
char *getenv(const char *name);
//返回:存在,返回指向name的指针,若无匹配的,为NULL
- fork函数和execve函数的区别:
1)fork函数在新的子进程中运行相同的程序,新的子进程是父进程的一个复制品。
2)execve函数在当前进程的上下文中加载并运行一个新的程序,它会覆盖当前进程的地址空间,但并没有创建一个新进程。
3)新的程序仍然有相同的pid,并且继承了调用execve函数时已打开的所有文件描述符。
信号
- 信号就是一条小消息,通知进程系统中发生了一个某种类型的事件。
- 发送信号:内核通过更新目的进程上下文中的某个状态,发送一个信号给目的进程。
- 接收信号:当目的进程被内核强迫以某种方式对信号的发送做出反应时,目的进程就接收了信号。通过信号处理程序捕获信号。
- 发送信号的方式
1)/bin/kill
2)键盘发送信号
3)kill函数
4)alarm函数
- 接收信号的默认行为
1)进程终止
2)进程终止并转储存储器
3)进程停止直到被SIGCONT信号重启
4)进程忽略该信号。
- 信号处理问题
1)待处理信号被阻塞
2)待处理信号不会排队等待
3)系统调用可以被中断
- 可移植的信号处理,信号处理语义的差异,是UNIX信号处理的一个缺陷。
教材学习中的问题和解决过程
(一个模板:我看了这一段文字 (引用文字),有这个问题 (提出问题)。 我查了资料,有这些说法(引用说法),根据我的实践,我得到这些经验(描述自己的经验)。 但是我还是不太懂,我的困惑是(说明困惑)。【或者】我反对作者的观点(提出作者的观点,自己的观点,以及理由)。 )
- 问题1:XXXXXX
- 问题1解决方案:XXXXXX
- 问题2:XXXXXX
- 问题2解决方案:XXXXXX
- ...
代码调试中的问题和解决过程
- 问题1:XXXXXX
- 问题1解决方案:XXXXXX
- 问题2:XXXXXX
- 问题2解决方案:XXXXXX
- ...
代码托管
(statistics.sh脚本的运行结果截图)
上周考试错题总结
- 错题1及原因,理解情况
- 错题2及原因,理解情况
- ...
结对及互评
点评模板:
- 博客中值得学习的或问题:
- xxx
- xxx
- ...
- 代码中值得学习的或问题:
- xxx
- xxx
- ...
- 其他
本周结对学习情况
- [结对同学学号1](博客链接)
- 结对照片
- 结对学习内容
- XXXX
- XXXX
- ...
其他(感悟、思考等,可选)
xxx xxx
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。 耗时估计的公式 :Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
计划学习时间:XX小时
实际学习时间:XX小时
改进情况:
(有空多看看现代软件工程 课件 软件工程师能力自我评价表)