20145319 《信息安全系统设计基础》第十三周课后总结

20145319 《信息安全系统设计基础》第十三周课后总结

一 教材内容总结

基本概念

  • 并发:逻辑控制流在时间上重叠
  • 并发程序:使用应用级并发的应用程序称为并发程序
  • 三种基本的构造并发程序的方法
    • 进程:用内核来调用和维护,有独立的虚拟地址空间,显式的进程间通信机制
    • I/O多路复用,应用程序在一个进程的上下文中显式的调度控制流。逻辑流被模型化为状态机。
    • 线程,运行在一个单一进程上下文中的逻辑流。由内核进行调度,共享同一个虚拟地址空间

基于进程的并发编程

  • 常用构造并发进程的函数
    • fork
    • exec
    • waitpid
  • 基于进程的并发服务器(以一个基于进程的echo服务器为例说明几点)
    • 必须包括一个一个SIGCHLD处理程序,来回收僵死子进程的资源
    • 父子进程必须关闭各自的connfd拷贝,以避免存储器泄露
    • 因为套接字的文件表表项中的引用计数,直到父子进程的connfd都关闭了,到客户端的连接才会终止
  • 关于进程的优劣
    • 优点:一个进程不可能不小心覆盖两一个进程的虚拟存储器,可以防止虚拟存储器被错误覆盖
    • 缺点:独立的地址空间使得进程共享状态信息变得更加困难,开销很高

基于I/O多路复用的并发编程

  • I/O多路复用技术的优劣
    • 优点:
      • 比起基于进程的设计给了程序员更多的对程序行为的控制
      • 运行在单一进程上下文中,因此,每个逻辑流都能访问该进程的全部地址空间,使得流之间共享数据变得很容易
      • 事件驱动设计比较高效,因为不需要进程上下文切换来调度新的流
    • 缺点:
      • 编码复杂
      • 不能充分利用多核处理器

基于线程的并发编程

  • 多个进程运行在单一进程的上下文中,因此共享这个进程的虚拟地址空间的所有内容
  • 线程执行模型
    • 主线程:每个进程开始时都是单一线程,该线程被称作主线程
    • 对等线程:某个时刻,主线程创建的进程
    • 对等线程池:线程不同于进程是按照父子层次组织的,而是组成一个对等池
      • 影响:线程可以杀死它的任何对等线程,或等待对等线程终止每个对等线程读写时候共享数据
    • 线程执行不同于进程执行,因为线程上下文比较小,所以上下文切换较快
  • Posix线程
    • 线程例程:线程的代码和本地数据被封装在一个线程例程中。每一个线程例程都以一个通用指针作为输入,并返回一个通用指针
  • 创建线程
    • pthread_create函数:int pthread_create(pthread_t *tid, pthread_attr *attr, func *f, void *arg),创建一个新线程,并在新线程上下文中运行线程例程f,attr参数通常为NULL
    • 返回的参数tid包含新线程的ID,可以通过调用pthread_self来获得
  • 终止线程
    • 顶层的线程范例返回,线程会隐式的终止
    • 调用pthread_exit,线程会显示的终止
    • 对等线程调用Unix的exit函数,终止进程以及与进程相关的所有线程
    • 对等现场通过当前线程ID调用pthread_cancle函数
  • 回收已经终止线程的资源
    • pthread _join函数会阻塞,直到线程tid终止,回收已终止线程占用的所有存储器资源。pthread _join函数只能等待一个指定的线程终止
  • 分离线程
    • 可结合:一个可结合的线程能被其他线程杀死或者回收资源
    • 分离:不能被其他线程回收或者杀死,其存储器资源在它终止时自动释放
    • 默认情况下,线程被创建成都是可结合的
  • 初始化线程
    • int pthread _once(pthread_once_t *once_control, void(*init_routine)(void))函数允许初始化与线程例程相关的状态。
    • once _control变量是一个全局或者静态变量,总是被初始化为PTHREAD _ONCE _INIT

多线程程序中的变量共享

  • 线程存储器模型
    • 每个线程有自己独立的线程上下文,但是共享剩余的进程上下文
    • 存储器是不共享的,但是虚拟存储器是共享的
  • 变量映射到存储器
    • 局变量:虚拟存储器的读/写区域只会包含每个全局变量的一个实例。
    • 本地自动变量:定义在函数内部但没有static属性的变量。
    • 本地静态变量:定义在函数内部并有static属性的变量
  • 共享变量
    • 若变量v是共享的,当且仅当它的一个实例被一个以上的线程引用

用信号量同步线程

  • 共享变量引入了同步错误的可能
  • 线程I的循环代码分解成五部分
    • Hi:在循环头部的指令块
    • Li:加载共享变量cnt到寄存器%eax的指令,%eax表示线程i中的寄存器%eax的值
    • Ui:更新(增加)%eax的指令
    • Si:将%eaxi的更新值存回到共享变量cnt的指令
    • Ti:循环尾部的指令块
  • 进度图
    • 安全轨迹线:绕开不安全区的轨迹线
    • 不安全轨迹线:接触到任何不安全区的轨迹线就叫做不安全轨迹线
    • 任何安全轨迹线都能正确的更新共享计数器
  • 信号量
    • 当有多个线程在等待同一个信号量时,你不能预测V操作要重启哪一个线程。
    • 信号量不变性:一个正在运行的程序绝不能进入这样一种状态,也就是一个正确初始化了的信号量有一个负值
  • 使用信号量实现互斥
    • 二元信号量:将每个共享变量与一个信号量s联系起来,然后用P(S)和V(s)操作将这种临界区包围起来
    • 互斥锁:以提供互斥为目的的二元信号量
  • 利用信号量来调度共享资源
    • 生产者—消费者问题:
      • 生产者产生项目并把他们插入到一个有限的缓冲区中,消费者从缓冲区中取出这些项目,然后消费它们
    • 读者-写者问题:
      • 读者优先,要求不让读者等待,除非已经把使用对象的权限赋予了一个写者。
      • 写者优先,要求一旦一个写者准备好可以写,它就会尽可能地完成它的写操作

其他并发问题

  • 线程安全性:
    • 线程安全:当且仅当被多个并发线程反复地调用时,它会一直产生正确的结果
  • 线程不安全的类
    • 不保护共享变量的函数
    • 保持跨越多个调用的状态的函数。
    • 返回指向静态变量的指针的函数(解决办法:重写函数和加锁拷贝)
    • 调用线程不安全函数的函数
  • 可重入性
    • 可重入函数:当它们被多个线程调用时,不会引用任何共享数据
    • 显式可重入:没有指针,没有引用静态或全局变量
    • 隐式可重入:允许它们传递指针
  • 竞争
    • 竞争:当一个程序的正确性依赖于一个线程要在另一个线程到达y点之前到达它的控制流中的x点时,就会发生竞争
    • 消除方法:动态的为每个整数ID分配一个独立的块,并且传递给线程例程一个指向这个块的指针
  • 死锁
    • 一组线程被阻塞了,等待一个永远也不会为真的条件(例如进程p1拥有资源R1等待资源R2,进程P2又有资源R2等待资源R1)

三 代码托管

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 0/0 1/1 20/20 学习常用linux命令
第二周 100/100 1/2 20/40 学习vim,gdb等用法
第三周 100/200 1/3 15/55
第四周 0/300 0/3 10/65
第五周 100/400 1/4 15/80 重温了汇编相关知识
第六周 0/400 1/5 15/95 学习了Y86
第七周 100/500 1/6 15/110 学习了存储器相关知识
第八周 0/500 2/8 20/130 复习
第九周 150/650 2/10 15/145 学习了I/O相关知识
第十周 300/950 2/12 20/165 学习了linux命令代码
第十一周 200/1150 3/15 20/185 学习了异常流相关知识
第十二周 200/1350 3/18 20/205 复习I/O,fork相关代码
第十三周 150/1500 2/20 20/225 学习了并发,WEB相关知识

posted on 2016-12-11 22:35  20145319钟轲  阅读(142)  评论(1编辑  收藏  举报