zoukankan      html  css  js  c++  java
  • CSAPP笔记(第八章 异常控制流)-01

    第八章的内容为p537~p586, 分2部分, p537~p562, p563~p586.

    摘要

    本章主要讲了操作系统是如何处理任务, 任务之间是如何进行协调的.

    异常

    异常就是用来改变响应处理器状态变化的, CPU会暂时放下手上的任务, 进行异常的处理. 处理完之后有3种结果:

    1. 返回当前指令
    2. 跳到下一个指令
    3. 结束当前进程

    异常需要硬件和软件共同工作. 异常都有编号, 其中一部分由CPU设计者分配, 剩下的由操作系统内核设计者分配. 异常表的起始地址放在一个叫异常表基址寄存器的特殊CPU寄存器中.

    常见的异常有被零除, 缺页, 内存访问违例, 断点, 算术运算溢出, 系统调用, I/O设备信号等.

    异常的类别, 中断(interrupt), 陷阱(trap), 故障(fault), 终止(abort)

    x86-64系统定义了256种不同的异常类型, 0~31号由Intel架构师定义, 因此对任何x86-64系统都是一样的. 其他号码由操作系统定义, 所以不同的操作系统有差异.

    进程

    进程是一个执行中程序的实例. 每个程序都运行在某个进程的上下文(context)中. 上下文包含一组状态, 包括代码, 数据, 栈, 通用目的寄存器的内容, 程序计数器, 环境变量以及打开文件描述符的集合.

    多个流并发地执行的一般现象被称为并发(concurrency), 一个进程和其他进程轮流运行称为多任务(multitasking), 一个进程执行它的控制流的一部分的每个时间段叫做时间片(time slice), 多任务也叫时间分片(time slicing). 并发与CPU核数无关. 如果2个流并行地运行在不同CPU核上或者不同的计算机上, 叫做并行流(parallel flow), 并行的运行(running in parallel), 并行地执行(parallel execution).

    内存的分配. 底部留给用户程序, 顶部留给内核.

    用户模式与内核模式

    处理器通常用某个控制寄存器中的一个模式位(mode bit)来提供标识是否内核模式, 当设置了模式位时, 进行就运行在内核模式, 可以执行所有指令, 且可以访问系统中的任何内存位置. 没有设置模式位时, 进行运行在用户模式中, 不运行执行特权指令(privileged instruction), 比如停止处理器, 改变模式位, 或者发起一个I/O操作, 也不允许直接引用内核区中的代码和数据, 任何这样的尝试都会导致致命的保护故障. 必须通过系统调用接口间接地访问内核代码和数据.

    Linux提供了/proc文件系统, 可以在用户模式下访问内核数据结构的内容. 如/proc/cpuinfo访问cpu类型, /proc//maps访问某个特殊进行使用的内存段.

    上下文切换

    当内核代表用户执行系统调用时, 可能会发生上下文切换, 如果系统调用因为等待某个事件而发生阻塞时, 内核可以让当前进行休眠, 切换到另一个进程. 比如一个read系统调用需要访问磁盘, 而磁盘数据可能要几十毫秒才能到达内存, 内核可以切换到另一个进程, 而当数据从磁盘到达后, 会有一个磁盘中断, 内核再切换回原进程, 继续执行.

    进程控制

    pid = fork()函数会复制当前进程, 开启一个子进程, 根据pid的不同, 程序内可以判断是父进程还是子进程, pid为0则在子进程, pid为负则报错, pid为正则在父进程.

    #include <sys/types.h>
    #include <unistd.h>
    
    pid_t getpid(void); //返回调用进程PID
    pid_t getppid(void); //返回调用进程的父进程PID
    

    进程三状态

    1. 运行(running). 要么在cpu上执行, 要么等待被执行且最终被内核调度.
    2. 停止(stopped). 进程被挂起(suspended), 且不会被调度, 可以认为是暂停了, 直到等待SIGCONT信号才会再次运行.
    3. 终止(terminated). 进程永远停止了. 有三种原因1. 收到终止信号. 2. 从主程序返回. 3. 调用exit函数.
    #include <sys/types.h>
    #include <unistd.h>
    
    pid_t fork(void);
    

    子进程得到与父进程用户级虚拟地址空间相同的一份副本, 包括代码, 数据段, 堆, 共享库, 用户栈, 子进程还获得与父进程任何打开文件描述符相同的副本(子进程可以读写父进程打开的任何文件).

    关于fork的理解去看了左耳朵耗子的几篇文章. 一个FORK的面试题, VFork挂掉的一个问题.

    回收子进程

    当一个进程终止时, 内核不是立刻将它清除, 进程被保持在终止状态, 直到被父进程回收(reaped), 终止还未被回收称为僵死进程(zombie).

    如果父进程终止了, 内核会安排init进程进行回收. init进程的PID为1, 是系统启动时内核创建的, 不会终止, 是所有进程的祖先.

    #include <sys/types.h>
    #include <sys/wait.h>
    
    pid_t waitpid(pid_t pid, int *statusp, int options);
    

    waitpid用来挂起父进程, 等待子进程被回收.

  • 相关阅读:
    C# 建立快捷方式
    ae中gp执行 Error HRESULT E_FAIL has been returned from a call to a COM component错误
    AE编辑点要素编辑
    噱头还是革命 云计算“泡沫”五年后改变世界? 狼人:
    分析:英特尔收购McAfee的三大意义 狼人:
    云安全:防护“工具”还是攻击“利器” 狼人:
    热点:安全问题是否能将DNS推入云服务 狼人:
    迈克菲收购tenCube 打造新一代移动安全平台 狼人:
    戴尔推免费浏览器安全工具 可隔离恶意软件 狼人:
    黑帽大会:HTTPS和SSL协议存在安全漏洞 狼人:
  • 原文地址:https://www.cnblogs.com/winwink/p/CSAPP_Note_Chapter8_Exception_01.html
Copyright © 2011-2022 走看看