教材学习内容总结
8.1 异常
•异常就是控制流中的突变,用来响应处理器状态中的某些变化
•8.1.1 异常处理 •系统中可能的每种类型的异常都分配了一个唯一的非负整数的异常号。 •处理器:被零除、缺页、存储器访问违例、断点以及算术溢出
•操作系统:系统调用和来自外部I/O设备的信号
•8.1.2异常的类别 •中断 •来自I/O设备的信号,异步,总是返回到下一条指令
•陷阱 •有意的异常,同步,总是返回到下一条指令
•故障 •潜在可恢复的错误,同步,可能返回到当前指令
•终止 •不可恢复的错误,同步,不会返回
•8.1.3 Linux系统中的异常 •Linux故障和终止 •除法错误:异常号:0,通常报告为“浮点异常”
•一般保护故障:异常号:13,Linux不会尝试回复这类故障,通常报告为“段故障”
•缺页:异常号:14,是会重新执行产生故障的指令的一个异常事例
•机器检查:异常号:18,从不返回控制给应用程序
•Linux系统调用 •每个系统调用都有一个唯一的整数号,对应于一个到内核中跳转表的偏移量
•将系统调用和与他们相关的包装函数称为系统级函数
8.2 进程
•系统中的每个程序都是运行在某个进程的上下文中的。上下文是由程序正确运行所需的状态组成的 •8.2.1 逻辑控制流 •程序计数器(PC)的值的序列叫做逻辑控制流,简称逻辑流
•每个进程执行它的流的一部分,然后被抢占(暂时挂起),然后轮到其他进程
•8.2.2 并发流 •一个逻辑流的执行在时间上与另一个流重叠,称为并发流
•并发:多个流并发的执行的一般现象
•多任务:一个进程和其他进程轮流运行
•时间片:一个进程执行它的控制流的一部分的每一段时间
•习题8.1
•8.2.3 私有地址空间 •这个空间中某个地址相关联的那个存储器字节是不能被其他进程读或者写的
•8.2.4 用户模式和内核模式 •当设置了模式位时,进程就运行在内核模式中
•没有设置模式位时,进程就运行在用户模式中。用户模式中的进程不允许执行特权指令。
•进程从用户模式变位内核模式的唯一方法是通过诸如中断、故障或者陷入系统调用这样的异常。
•/proc文件系统允许用户模式进程访问内核数据结构的内容
•8.2.5 上下文切换 •上下文切换:是较高形式的异常控制流来实现多任务
•调度:在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占的进程。这种决定叫做调度
•当内核代表用户执行系统调用时,可能会发生上下文切换。如果系统调用因为等待某个事件发生阻塞,那么内核可以让当前进程休眠,切换到另一个进程
•中断也可能引发上下文切换
8.3 系统调用错误处理
•定义错误报告函数,简化代码
•错误处理包装函数
8.4 进程控制
•8.4.1获取进程ID •每个进程都有一个唯一的正数进程ID
•gitpid函数返回调用进程的PID,getppid函数返回它的父进程的PID(创建调用进程的进程)
•8.4.2 创建和终止进程 •进程状态:运行、停止、终止
•exit函数以status退出状态来终止进程
•fork函数 •父进程通过调用fork函数创建一个新的运行子进程
•当父进程调用fork时,子进程可以读写父进程中打开的任何文件
•父进程和子进程之间最大的区别在于有不同的PID
•调用一次,返回两次
•并发执行
•相同但是独立的地址空间
•共享文件
习题8.2
•8.4.3 回收子进程 •僵死进程没有运行,他们仍然消耗系统的存储器资源
•一个进程可以通过调用waitpid函数来等待它的子进程终止或停止
•1.判定等待集合的成员(由参数pid确定) •pid>0,等待集合就是一个单独的子进程,它的进程ID等于pid
•pid=-1,等待集合就是由父进程所有的子进程组成的
•2.修改默认行为 •WNOHANG:默认行为是挂起调用进程,直到有子进程终止
•WUNTRCED:默认行为是只返回已经终止的子进程
•WNOHANG|WUNTRCED:立即返回
•3.检查已回收子进程的退出状态
•4.错误条件 •如果调用进程没有子进程,那么waitpid返回-1,设置errno为ECHILD
•如果waidpid函数被一个信号中断,那么它返回-1,并设置errno为EINTR
•5.wait函数
•6.使用waitpid的示例
•8.4.4 让进程休眠 •sleep函数将一个进程挂起一段指定的时间
•pause函数让调用函数休眠,直到该进程收到一个信号
•8.4.5 加载并运行程序 •execve函数在当前进程的上下文中加载并运行一个新程序,execve调用一次并从不返回 •argv参数列表,envp环境变量
•getenv函数
8.5 信号
•Unix信号:更高层的软件形式的异常,允许进程中断其他进程
•P505:30种不同类型的信号表
•8.5.1 信号术语 •发送信号:1)内核检测到一个系统事件 2)一个进程调用了kill函数
•接收信号:当目的进程被内核强迫以某种方式对发送的信号作出反应时,目的进程就接收了信号
•待处理信号:一个只发出而没有被接收的信号
•8.5.2 发送信号 •1.进程组 •每个进程都只属于一个进程组
•一个进程可以通过使用setpigd函数来改变自己或者其他进程的进程组
•2.用/bin/kill程序发送信号 •一个为负的PID会导致信号被发送到进程组PID中的每个进程中
•3.从键盘发送信号
•4.用kill函数发送信号
•5.用alarm函数发送信号
•8.5.3 接收信号 •如果集合是非空的,那么内核选择集合中的某个信号k,并且强制p接收信号k
•signal函数可以改变和信号signum相关联的行为
•8.5.4 信号处理问题 •捕获多个信号时的问题: •待处理信号被阻塞
•待处理信号不会排队等待
•系统调用可以被中断
•8.5.5 可移植的信号处理 •不同系统之间,信号处理语义有差异
•sigaction函数明确地指定它们想要的信号处理语义
•8.5.6 显式地阻塞和取消阻塞 •应用程序可以使用sigprocmask函数显式地阻塞和取消阻塞选择的信号
•sigprocmask函数改变当前已阻塞信号的集合
8.6非本地跳转
•通过setjmp和longjmp函数来提供
•setjmp函数只被调用一次,但返回多次:一次是当第一次调用setjmp,而调用环境保存在缓冲区env中时,一次是为每个相应的longjmp调用
•longjmp只调用一次,但从不返回
•非本地跳转的一个重要应用就是允许从一个深层嵌套的函数调用中立即返回,通常是由检测到某个错误情况引起的
•非本地跳转的另一个重要应用是使一个信号处理程序分支到一个特殊的代码位置,而不是返回到达中断了的指令位置
8.7 操作进程的工具
•Linux系统提供监控和操作进程的工具:打印一个正在运行的程序和它的子进程调用的每个系统调用的轨迹(STRACE)、列出当前系统中包括僵死进程的进程(PS)、打印出关于当前进程资源使用的信息(TOP)、显示进程的存储器映射(PMAP)、虚拟文件系统(/proc)