学习目标
找出全书你认为学得最差的一章,深入重新学习一下,要求(期末占5分):
总结新的收获-给你的结对学习搭档讲解或请教,并获取反馈
第八章内容总结
新的收获:因为认为异常和信号这方面的学习不够认真全面,所以这周学习的主要内容第八章。从本章中,我巩固了之前在其他课中学习的一些知识,如:异常的处理、异常的识别、处理父子进程等,也学习了一些新的知识,如自己设置函数参数控制转移,从而将不同课程的知识结合起来,而不是单纯的背、记。
教材学习内容总结
异常
异常处理
- 当处理器监测到有事件发生时,通过一张叫做异常表的跳转表,进行一个间接过程调用,到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序),而这里所谓的事件就是在处理器中,状态被编码为不同的位和信号,状态变化就是事件。
- 系统中可能的某种类型的异常都分配了一个唯一的非负整数的异常号。异常号是到异常表中的索引。
- 异常是控制流中的突变,用来响应处理器状态中的某些变化
- 异常控制流简介(ECF)
1、控制转移:从ak到ak+1指令的过渡。
2、异常控制流(Exceptional Control Flow, ECF):现代操作系统通过使控制流发生突变来对系统状态做出反应。
3、ECF是操作系统用来实现I/O、进程和虚拟存器的基本机制,是计算机系统中实现并发的基本机制。 异常处理 - 系统中可能的每种类型的异常都分配了一个唯一的非负整数的异常号。
- ECF软件异常机制——C++和Java有try,catch,和throw,C中非本地跳转是setjmp和longjmp
处理器的设计者:被除零、缺页、存储器访问违例、断点以及算数溢出。
操作系统内核的设计者分配的:系统调用和来自意外的I/O设备的信号。
异常号:到异常表中的索引异常表基址寄存器:异常表的起始地址存放的位置。3、异常与过程调用的异同:
- 过程调用时,在跳转到处理器之前,处理器将返回地址压入栈中。然而,根据异常的类型,返回地址要么是当前指令,要么是下一条指令。
- 处理器把一些额外的处理器状态压入栈里,在处理程序返回时,重新开始被中断的程序会需要这些状态。
- 如果控制从一个用户程序转移到内核,那么所有这些项目都被压到内核栈中,而不是压到用户栈中。
- 常处理程序运行在内核模式下,意味着它们对所有的系统资源都有完全的访问权限。
异常的处理方式:
- 处理器检测到有异常发生
- 通过异常表,进行间接过程调用,到达异常处理程序
- 完成处理后:①返回给当前指令②返回给下一条指令③终止
异常的类别
中断处理程序:硬件中断的异常处理程序。
终止: 不可恢复的错误,同步,不会返回
陷阱: 有意的异常,同步,总是返回到下一条指令
中断: 来自I/O设备的信号,异步,总是返回到下一条指令
故障指令:执行当前指令导致异常
故障: 潜在可恢复的错误,同步,可能返回到当前指令
进程
- 异常是允许操作系统提供进程的概念所需要的基本构造块。
- 进程是一个执行中的程序的实例。
- 上下文由程序正确运行所需要的状态组成的.
这个状态包括存放在存储器中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。 - 进程提供给应用程序的关键抽象:一个独立的逻辑控制流,独占地使用处理器;一个私有的地址空间,独占地使用存储器系统。
逻辑控制流
- 程序计数器:唯一的对应于包含在程序的可执行目标文件中的指令,或者是包含在运行时动态链接到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流,简称逻辑流。
- 并发流是一个逻辑流的执行在时间上与另一个流重叠。
- 多任务也叫时间分片。
私有地址空间
- 这个空间中某个地址相关联的那个存储器字节是不能被其他进程读或者写的
上下文切换
- 是较高形式的异常控制流来实现多任务
- 在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占的进程。这种决定叫做调度
- 当内核代表用户执行系统调用时,可能会发生上下文切换。如果系统调用因为等待某个事件发生阻塞,那么内核可以让当前进程休眠,切换到另一个进程,中断也可能引发上下文切换。
获取进程ID
每个进程都有一个唯一的正数进程ID gitpid函数返回调用进程的PID,getppid函数返回它的父进程的PID(创建调用进程的进程)
代码如下:
#include<sys/types.h>
#include<unistd.h>
pid_t getpid(void);
pid_t getppid(void);
创建和终止进程
- 回收子进程——当一个进程由于某种原因终止,内核不会将他马上清除,而是将进程保持在已终止的状态中,直到被他的父进程回收。
当父进程回收已终止的子进程时,内核将子进程的退出状态传递给父进程,然后抛弃已终止的进程。一个终止了但还未被回收的进程称为僵死进程。
一个进程可以通过调用waitpid函数来等待它的子进程终止或者停止。默认地,当option=0时,waitpid挂起调用进程的执行,直到它的等待集合中的一个子进程终止。 - 进程状态:运行、停止、终止 exit函数以status退出状态来终止进程
父进程通过调用fork函数创建一个新的运行子进程,当父进程调用fork时,子进程可以读写父进程中打开的任何文件,父进程和子进程之间最大的区别在于有不同的PID,调用一次,返回两次。回收子进程后僵死进程没有运行,他们仍然消耗系统的存储器资源 一个进程可以通过调用waitpid函数来等待它的子进程终止或停止
代码如下:#include<sys/types.h> #include<sys/wait.h> pid_t waitpid(pid_t pid,int *status,int options);
- 判定等待集合的成员(由参数pid确定) pid>0,等待集合就是一个单独的子进程,它的进程ID等于pid pid=-1,等待集合就是由父进程所有的子进程组成的,修改默认行为 WNOHANG:默认行为是挂起调用进程,直到有子进程终止 WUNTRCED:默认行为是只返回已经终止的子进程 WNOHANG|WUNTRCED:立即返回
- 检查已回收子进程的退出状态
错误条件 如果调用进程没有子进程,那么waitpid返回-1,设置errno为ECHILD 如果waidpid函数被一个信号中断,那么它返回-1,并设置errno为EINTR
让进程休眠
sleep函数将一个进程挂起一段指定的时间
代码如下:#include<unistd.h> unsigned int sleep(unsigned int secs); pause函数让调用函数休眠,直到该进程收到一个信号 #include<unisted.h> int pause(void);
信号
- 其他信号对应于内核或者其他用户进程中较高层的软件事件,而底层的硬件异常是由内核异常处理程序处理的,正常情况下,对用户进程而言是不可见的。
- 发送信号的两个不同步骤:
发送信号:内核通过更新目的进程上下文中的某个状态,发送(递送)一个信号给目的进程。
接收信号:信号处理程序捕获信号的基本思想。 - 发送信号的两个原因:内核监测到一个系统事件,比如被零除错误或者子进程终止&一个进程调用了kill函数,显式地要求内核发送一个信号给目的进程。一个进程可以发送信号给它自己。
待处理信号:一个只发出而没有被接收的信号,一个进程可以有选择性地阻塞接收某种信号&待处理信号不会被接收,直到进程取消对这种信号的阻塞。一个待处理信号最多只能被接受一次,pending位量:维护着待处理信号集合,blocked向量:维护着被阻塞的信号集合。
信号
信号就是一条小消息,通知进程系统中发生了一个某种类型的事件。
发送信号的方式有很多,/bin/kill——键盘发送信号——kill函数——alarm函数
接收信号的默认行为有很多,进程终止——进程终止并转储存储器——进程停止直到被SIGCONT信号重启——进程忽略该信号。
信号处理问题——待处理信号被阻塞——待处理信号不会排队等待——系统调用可以被中断——可移植的信号处理,信号处理语义的差异,是UNIX信号处理的一个缺陷。
教材学习中的问题和解决过程
练习题
8.2
8.4
8.6: 编写一个叫做myecho的程序,打印出他的命令行参数和环境变量。
8.7 编写一个叫做snooze的程序,有一个命令行参数,用这个参数调用习题8.5中的snooze函数,然后终止。编写程序,使得用户可以通过在键盘上输入Ctrl-c中断snooze函数.
8.13/code/ecf/forkprob/下面程序的一种可能输出是什么?
代码调试中的问题和解决过程
问题:编写一个fgets函数的一个版本,叫做tfgets,他5s之后会超时,tfgets函数接受fgets相同的输入,如果用户在5s内部输入一个行,tfgets韩慧NULL。否则,他范湖一个指向输入行的指针。
解决方案:查阅fgets的main文档,得知 char fgets(char buf,int bufsize,FILE *stream);
这个应该是用alarm发送信号给自己,然后在信号处理程序里面做文章。显然,在tfgets里一开始需要调用fgets。然而,因为五秒时间到了,fgets还没有返回,所以我们必须在处理程序里直接跳转到某个tfgets的NULL返回。这就需要用到非本地跳转了。
其他感悟:
因为认为异常和信号这方面的学习不够认真全面,所以这周学习的主要内容第八章。从本章中,我巩固了之前在其他课中学习的一些知识,如:异常的处理、异常的识别、处理父子进程等,也学习了一些新的知识,如自己设置函数参数控制转移,从而将不同课程的知识结合起来.
结对以及互评:
本周结对学习情况
- 20155338
- 结对照片
- 我给他讲解了第八章的内容,他也发现自己有很多的不足之处,经过我们的共同研讨,他对异常控制这方面的知识有了进一步的了解。我们一起做了部分课后题,我还就重点给他详细解答。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 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 | |
第五周 | 400/1700 | 2/11 | 30/90 | |
第六周 | 300/2000 | 3/14 | 30/90 | |
第七周 | 200/2200 | 3/17 | 15/105 | |
第八周 | 300/2500 | 1/18 | 17/122 | |
第九周 | 300/2800 | 3/21 | 15/137 | |
第十周 | 200/3000 | 3/24 | 12/159 | |
第十一周 | 300/3300 | 2/26 | 11/170 | |
第十二周 | 200/3500 | 1/27 | 10/180 | |
第十三周 | 100/3600 | 2/29 | 7/187 | |
第十四周 | 200/3800 | 1/30 | 6/193 |