20145210《信息安全系统设计基础》第十一周学习总结
20145210《信息安全系统设计基础》第十一周学习总结
教材学习内容总结
异常及其种类
1.异常
·异常是异常控制流的一种形式,由硬件和操作系统实现
·异常是控制流中的突变,用来响应处理器状态中的某些变化
·当异常处理程序处理结束之后,会有三种结果:
·处理程序将控制返回给事件发生的时候正在执行的指令
·处理程序将控制返回给如果没有发生异常将会执行的下一条指令
·处理程序终止被终端的程序
2.异常处理
·在任何情况下,当处理器检测到有事件发生时,它就会通过一张叫做异常表的跳转表进行一个间接过程调用,到一个专门处理这类时间的操作系统子程序(异常处理程序)
·异常类似于过程调用,区别在:
·处理器压入栈的返回地址,是当前指令地址或者下一条指令地址。
·处理器也把一些额外的处理器状态压到栈里
·如果控制一个用户程序到内核,所有项目都压到内核栈里。
·异常处理程序运行在内核模式下,对所有的系统资源都有完全的访问权限。
3.异常的类别
异常分为四类:中断、陷阱、故障、终止
·中断:不是由任何一条专门的指令造成的
·陷阱、故障、终止:均为执行当前指令的结果,这类指令被称为故障指令
·系统调用:陷阱最重要的用途是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用
·故障:由错误情况引起,可能会被故障处理程序修正
·终止:不可恢复的致命错误造成的结果
4.Linux/IA32系统中的异常
·IA32系统中的异常示例
·IA32系统调用中常用的系统调用示例
进程
·进程:一个执行中的程序的实例
·上下文:由程序正确运行所需的状态组成
·进程提供给应用程序的关键抽象:
·一个独立的逻辑控制流:独占的使用处理器
·一个私有的地址空间:独占的使用存储器系统
1.逻辑控制流
·逻辑控制流:一系列的程序计数器PC的值,分别唯一的对应于包含子啊程序的可执行目标文件中的指令,或者是包含在运行时动态链接到程序的共享对象中的指令,这个PC值的序列就叫做逻辑控制流
·进程是轮流使用处理器的。每个进程执行它的流的一部分,然后被抢占,然后轮到其他进程。但是进程可以向每个程序提供一种假象,好像它在独占的使用处理器
·逻辑控制流的例子:异常处理程序、进程、信号处理程序、线程、Java进程
2.并发流
·并发流:一个逻辑流的执行在时间上与另一个流重叠,成为并发流,这两个流称为并发地运行
·并发:多个流并发地执行的一般现象称为并发
·多任务:一个进程和其他进程轮流运行,也叫时间分片
·时间片:一个进程执行他的控制流的一部分的每一时间段
·并行流:两个流并发地运行在不同的处理器核或计算机上,我们称他们为并行流,他们并行地运行,且并行地执行
·并发的思想与流运行的处理器核或者计算机数无关
·如果两个流在时间上重叠,那么他们就是并发的,即使他们是运行在同一个处理器上的
3.私有地址空间
·进程为程序提供的假象,好像它独占的使用系统地址空间
·一个进程为每个程序提供给他自己的私有地址空间
4.用户模式和内核模式
·设置模式位:进程运行在内核模式中
·不设置模式位:进程运行在用户模式中
·内核模式:一个运行在内核模式的进程可以执行指令集中的任何指令,并可以访问系统内存中任何存储器位置
·用户模式:用户模式的进程不允许执行特权指令,也不允许直接引用地址空间中内核区内的代码和数据,用户程序必须通过系统调用接口间接地访问内核代码和数据
·进程切换:进程从用户模式变为内核模式的唯一方法是通过诸如中断、故障或陷入系统调用这样的异常
·/proc文件系统:允许用户模式进程访问内核数据结构的内容
5.上下文切换
·上下文切换:操作系统内核使用一种称为上下文切换的较高层形式的异常控制流来实现多任务
·内核为每一个进程维持一个上下文
·调度:内核可以决定抢占当前进程,并重新开始一个先前被抢占的进程,这种决定叫做调度,由内核中称为调度器的代码处理的
·上下文切换:
1.保存当前进程的上下文
2.恢复某个先前被抢占的进程被保存的上下文
3.将控制传递给这个新恢复的进程
·引发上下文切换的原因:
·内核代表用户执行系统调度
·中断
系统调度错误处理
·系统会使用错误处理包装函数,系统级函数是小写,他们的包装函数名大写,包装函数调用基本函数,有任何问题就终止,如果没有问题和基本函数是一样的。
进程控制
进程控制相关函数整理:
·进程总是处于下面三种状态之一:
运行
停止
终止
·进程因为三种原因终止:
1.收到一个信号,该信号的默认行为是终止进程
2.从主程序返回
3.调用exit函数
·新创建的子进程几乎但不完全与父进程相同
·当父进程调用fork时,子进程可以读写父进程中打开的任何文件
·父进程与新创建的子进程的最大区别:PID不同
·fork函数与execve函数:
·fork函数:被调用一次,返回两次。父进程返回子进程的PID,子进程返回0
·在fork函数中,父进程和子进程是并发运行的独立进程
·父进程和子进程有相同的但是独立的地址空间
·子进程继承了父进程所有的打开文件
·调用fork函数n次,产生2的n次方个进程
·在新的子进程中运行相同的程序,新的子进程是父进程的一个复制品
·execve函数:一次调用从不返回
·在当前进程的上下文中加载并运行一个新的程序,他会覆盖当前进程的地址空间,但并没有创建一个新进程
·回收子进程:进程终止后还要被父进程回收,否则处于僵死状态。如果父进程没有来得及回收,内核会安排init进程来回收他们。init进程的PID为1
·waitpid函数:等待子进程停止或终止
·如果成功返回子进程PID,如果WNOHANG,返回0,其他错误返回-1
·判断等待集合的成员——pid
·修改默认行为——options
·检查已回收子进程的退出状态——status
·错误条件:如果调用进程没有子进程,那么waitpid返回-1,并且设置errno为ECHILD。如果waitpid被一个信号中断,那么他返回-1,并且设置errno为EINTR
·sleep函数:将一个进程挂起一段指定的时间
·pause函数:让调用函数休眠,直到该进程收到一个信号
信号
相关函数整理:
1.信号术语
·传递一个信号到目的进程的两个步骤:发送信号和接收信号
·发送信号的原因:
·内核检测到一个系统事件
·一个进程调用了kill函数,显式的要求内核发送一个信号给目的进程
·待处理信号:
·只发出没有被接收的信号
·任何时刻,一种类型至多只会有一个待处理信号,多的会被直接丢弃
·一个进程可以选择性的阻塞接受某种信号,被阻塞仍可以被发送,但是不会被接收
·一个待处理信号最多只能被接收一次。
·pending:待处理信号集合
·blocked:被阻塞信号集合
2.发送信号
·每个进程都只属于一个进程组
·进程组ID:正整数
·一个子进程和它的父进程属于同一进程组
·/bin/kill程序可以向另外的进程发送任意的信号,格式是:
/bin/kill -n m
·n是信号,m是进程或进程组
·当n>0时,发送信号n到进程m
·当n<0时,使信号|n|发送到进程组m中的所有进程
·kill
·进程通过调用kill函数发送信号给其他进程(包括自己)
·pid>0:kill函数发送sig信号给进程pid
·pid<0:kill函数发送信号sig给进程组abs(pid)中的每个进程
·alarm函数
·进程通过调用alarm函数向他自己发送SIGALRM信号
·返回前一次闹钟剩余的秒数,如果没有任何待处理的闹钟,则返回0
·signal函数:
·修改和信号相关联的默认行为
·通过以下三种方法之一改变和信号signum相关联的行为:
·若handler是SIG_IGN:忽略类型为signum的信号
·若handler是SIG_DFL:类型为signum的信号行为恢复默认行为
·否则,handler就是用户定义的函数的地址
代码实践内容总结
exec1
execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno中。
exec2
它与exec1的区别就在于exevp函数的第一个参数,exec1传的是ls,exec2直接用的arglist[0],不过由定义可得这两个等价,所以运行结果是相同的。
exec3
execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束。
指定了环境变量,然后依然执行了ls -l指令,成功后没有返回,所以最后一句话不会输出。运行结果同exec1
forkdemo1
先打印进程pid,然后调用fork函数生成子进程,休眠一秒后再次打印进程id,这时父进程打印子进程pid,子进程返回0。
父进程通过调用fork函数创建一个新的运行子进程。
调用一次,返回两次。一次返回到父进程,一次返回到新创建的子进程。
forkdemo2
调用两次fork,一共产生四个子进程,所以会打印四个aftre输出
forkdemo3
fork产生子进程,父进程返回子进程pid,不为0,所以输出父进程结果,子进程返回0,所以会输出子进程结果
forkdemo4
先打印进程pid,之后fork创建子进程,父进程返回子进程pid,所以输出parent,休眠十秒
子进程返回0,所以输出child与之后语句
forkgdb
父进程打印是先打印两句,然后休眠一秒,然后打印一句
子进程先打印一句,然后休眠一秒,然后打印两句
这两个线程是并发的,所以可以看到在一个线程休眠的那一秒,另一个线程在执行,并且线程之间相互独立互不干扰
psh1
依次输入要执行的指令与参数,回车表示输入结束,然后输入的每个参数对应到函数中,再调用对应的指令
第一个是程序名,然后依次是程序参数
psh2
比起1来,多了循环判断,不退出的话就会一直要你输入指令,并且对于子程序存在的状态条件
testbuf1
效果是先输出hello语句,然后保持在循环中不结束进程
testbuf2
效果和1相同,所以fflush(stdout)的效果和换行符\n是一样的。
testbuf3
将内容格式化输出到标准错误、输出流中
testpid
输出当前进程pid和当前进程的父进程的pid
testpp
问题在于没给pp分配空间就调用了pp[0]
testsystem
system()——执行shell命令,也就是向dos发送一条指令。这里是后面可以跟两个参数,然后向dos发送这两个命令,分别执行
waitdemo1
如果有子进程,则终止子进程,成功返回子进程pid。
waitdemo2
wait阻塞调用它的程序直到子进程结束,返回结束进程的PID,父进程通过传给wait的参数中获取子进程以何种方式退出。如果子进程调用exit退出,那么内核把exit的返回值存放到这个整数变量中的高八位,如果进程是被杀死的,那么内核将信号序号存放在这个变量的低7位,中间一位用来指明发生错误并产生了core dump
代码托管
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | |
---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 |
第零周 | 0/0 | 1/1 | 10/10 |
第一周 | 100/100 | 1/2 | 20/20 |
第二周 | 120/220 | 1/3 | 35/55 |
第三周 | 226/446 | 1/4 | 30/85 |
第五周 | 141/587 | 1/5 | 30/115 |
第六周 | 150/737 | 1/6 | 25/140 |
第七周 | 100/837 | 1/7 | 20/160 |
第八周 | 0/837 | 2/9 | 30/190 |
第九周 | 183/1020 | 2/11 | 20/210 |
第十周 | 521/1541 | 3/14 | 20/230 |
第十一周 | 426/1967 | 1/15 | 35/265 |
posted on 2016-11-27 23:16 20145210姚思羽 阅读(188) 评论(2) 编辑 收藏 举报